diff --git a/.eslintrc.js b/.eslintrc.js
index 766d211..f973206 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -6,18 +6,25 @@
   'root': true,
   'env': {
     'browser': true,
-    'es6': true
+    'es6': true,
+  },
+  'parserOptions': {
+    'ecmaVersion': 2017,
   },
   'rules': {
     // Enabled checks.
+    'brace-style': ['error', '1tbs'],
+    'curly': ['error', 'multi-line', 'consistent'],
     'no-extra-semi': 'error',
     'no-new-wrappers': 'error',
-    'no-restricted-properties': ['error', {
-      'object': 'document',
-      'property': 'getElementById',
-      'message': 'Use $(\'id\') or getSVGElement(\'id\') ' +
-          'from chrome://resources/js/util.js instead of ' +
-          'document.getElementById(\'id\')',
+    'no-restricted-properties': [
+      'error',
+      {
+        'object': 'document',
+        'property': 'getElementById',
+        'message': 'Use $(\'id\') or getSVGElement(\'id\') ' +
+            'from chrome://resources/js/util.js instead of ' +
+            'document.getElementById(\'id\')',
       },
     ],
     'semi': ['error', 'always'],
diff --git a/.gitignore b/.gitignore
index 53bde4d..09560d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -223,6 +223,7 @@
 /net/net_unittests_run.xml
 /net/Release
 /net/testserver.log
+/net/third_party/quiche
 /out*/
 /ppapi/native_client/nacl_irt.xml
 /ppapi/native_client/ppapi_lib.xml
@@ -255,6 +256,7 @@
 /sql/sql_unittests_run.xml
 /sync/sync.xml
 /sync_testserver.log
+/testing/libfuzzer/fuzzer_corpus_for_bots/
 /testserver.log
 # See third_party/.gitignore for entries covering src/third_party.
 /tools/.bisect-builds-cache.json
@@ -269,6 +271,7 @@
 /tools/metrics/histograms/histograms.before.pretty-print.xml
 /tools/metrics/histograms/enums.before.pretty-print.xml
 /tools/page_cycler/acid3
+/tools/skia_goldctl/
 /tools/swarming_client
 /tools/tryserver
 /tools/win/link_limiter/build
diff --git a/.gn b/.gn
index 6f27729..ea7a2f4 100644
--- a/.gn
+++ b/.gn
@@ -317,7 +317,6 @@
   "//third_party/Python-Markdown/*",
 
   # "//third_party/SPIRV-Tools/*",  # 30ish errors
-  "//third_party/WebKit/*",
   "//third_party/abseil-cpp/*",
   "//third_party/accessibility-audit/*",
   "//third_party/accessibility_test_framework/*",
@@ -413,7 +412,6 @@
   "//third_party/gif_player/*",
   "//third_party/glfw/*",
   "//third_party/glslang/*",
-  "//third_party/glslang-angle/*",
   "//third_party/google_appengine_cloudstorage/*",
   "//third_party/google_input_tools/*",
   "//third_party/googletest/*",
@@ -561,7 +559,6 @@
   "//third_party/speech-dispatcher/*",
   "//third_party/spirv-cross/*",
   "//third_party/spirv-headers/*",
-  "//third_party/spirv-tools-angle/*",
   "//third_party/sqlite/*",
   "//third_party/sqlite4java/*",
   "//third_party/stp/*",
diff --git a/AUTHORS b/AUTHORS
index 567fe15..6ec00b5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -103,11 +103,13 @@
 Attila Dusnoki <dati91@gmail.com>
 Avinaash Doreswamy <avi.nitk@samsung.com>
 Ayush Khandelwal <k.ayush@samsung.com>
+Azhar Shaikh <azhar.shaikh@intel.com>
 Balazs Kelemen <b.kelemen@samsung.com>
 Baul Eun <baul.eun@samsung.com>
 Behara Mani Shyam Patro <behara.ms@samsung.com>
 Bem Jones-Bey <bemajaniman@gmail.com>
 Bem Jones-Bey <bjonesbe@adobe.com>
+Ben Coe <bencoe@gmail.com>
 Ben Fiola <benfiola@gmail.com>
 Ben Karel <eschew@gmail.com>
 Ben Noordhuis <ben@strongloop.com>
@@ -115,6 +117,7 @@
 Benjamin Jemlich <pcgod99@gmail.com>
 Bernard Cafarelli <voyageur@gentoo.org>
 Bernhard M. Wiedemann <bwiedemann@suse.de>
+Bert Belder <bertbelder@gmail.com>
 Bhagirathi Satpathy <bhagirathi.s@samsung.com>
 Bhanukrushana Rout <b.rout@samsung.com>
 Biljith Jayan <billy.jayan@samsung.com>
@@ -252,6 +255,7 @@
 Ernesto Mudu <ernesto.mudu@gmail.com>
 Etienne Laurin <etienne@atnnn.com>
 Eugene Kim <eugene70kim@gmail.com>
+Eugene Sudin <eugene@sudin.pro>
 Eunseok Oh <fivesilverstone@gmail.com>
 Evan Peterson <evan.peterson.ep@gmail.com>
 Evan Wallace <evan.exe@gmail.com>
@@ -271,6 +275,7 @@
 Frédéric Jacob <frederic.jacob.78@gmail.com>
 Frédéric Wang <fred.wang@free.fr>
 Fu Junwei <junwei.fu@intel.com>
+Gabor Rapcsanyi <g.rapcsanyi@samsung.com>
 Gaetano Mendola <mendola@gmail.com>
 Gajendra N <gajendra.n@samsung.com>
 Gajendra Singh <wxjg68@motorola.com>
@@ -309,6 +314,7 @@
 Halton Huo <halton.huo@gmail.com>
 Halton Huo <halton.huo@intel.com>
 Hans Hillen <hans.hillen@gmail.com>
+Hao Li <hao.x.li@intel.com>
 Haojian Wu <hokein.wu@gmail.com>
 Hari Singh <hari.singh1@samsung.com>
 Harpreet Singh Khurana <harpreet.sk@samsung.com>
@@ -422,7 +428,6 @@
 John Yani <vanuan@gmail.com>
 John Yoo <nearbyh13@gmail.com>
 Johnson Lin <johnson.lin@intel.com>
-Jon Kunkee <jkunkee@microsoft.com>
 Jonathan Frazer <listedegarde@gmail.com>
 Jonathan Garbee <jonathan@garbee.me>
 Jonathan Hacker <jhacker@arcanefour.com>
@@ -491,7 +496,6 @@
 Kingshuk Jana <kingshuk.j@samsung.com>
 Kirill Bobyrev <kirillbobyrev@gmail.com>
 Kirill Ovchinnikov <kirill.ovchinn@gmail.com>
-Kirk Shoop <kirk.shoop@microsoft.com>
 Klemen Forstnerič <klemen.forstneric@gmail.com>
 Kodam Nagaraju <k2.nagaraju@samsung.com>
 Konrad Dzwinel <kdzwinel@gmail.com>
@@ -665,6 +669,7 @@
 Paul Sapunaru <paul.sapunaru@intel.com>
 Paul Wicks <pwicks86@gmail.com>
 Pavan Kumar Emani <pavan.e@samsung.com>
+Pavel Golikov <paullo612@ya.ru>
 Pavel Ivanov <paivanof@gmail.com>
 Pawel Forysiuk <p.forysiuk@samsung.com>
 Paweł Hajdan jr <phajdan.jr@gmail.com>
@@ -678,6 +683,7 @@
 Peter Gal <pgal.u-szeged@partner.samsung.com>
 Peter Molnar <pmolnar.u-szeged@partner.samsung.com>
 Peter Snyder <snyderp@gmail.com>
+Peter Wong <peter.wm.wong@gmail.com>
 Philip Hanson <philip.hanson@intel.com>
 Philipp Hancke <fippo@andyet.net>
 Philipp Hancke <philipp.hancke@googlemail.com>
@@ -712,6 +718,7 @@
 Ramya Vadlamudi <ramya.v@samsung.com>
 Randy Posynick <randy.posynick@gmail.com>
 Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
+Raul Tambre <raul@tambre.ee>
 Raveendra Karu <r.karu@samsung.com>
 Ravi Nanjundappa <nravi.n@samsung.com>
 Ravi Phaneendra Kasibhatla <r.kasibhatla@samsung.com>
@@ -771,7 +778,6 @@
 Sathish Kuppuswamy <sathish.kuppuswamy@intel.com>
 Satoshi Matsuzaki <satoshi.matsuzaki@gmail.com>
 Sayan Nayak <sayan.nayak@samsung.com>
-Scott Blomquist <sblom@microsoft.com>
 Scott D Phillips <scott.d.phillips@intel.com>
 Sean Bryant <sean@cyberwang.net>
 Sean DuBois <seaduboi@amazon.com>
@@ -795,6 +801,7 @@
 Shanmuga Pandi M <shanmuga.m@samsung.com>
 Shaobo Yan <shaobo.yan@intel.com>
 Shashi Kumar <sk.kumar@samsung.com>
+Shen Yu <shenyu.tcv@gmail.com>
 Sherry Mou <wenjinm@amazon.com>
 Shez Baig <sbaig1@bloomberg.net>
 Shigeki Ohtsu <shigeki.ohtsu@gmail.com>
@@ -876,7 +883,6 @@
 Ting Shao <ting.shao@intel.com>
 Tom Callaway <tcallawa@redhat.com>
 Tom Harwood <tfh@skip.org>
-Tom Tan <Tom.Tan@microsoft.com>
 Tomas Popela <tomas.popela@gmail.com>
 Torsten Kurbad <google@tk-webart.de>
 Trent Willis <trentmwillis@gmail.com>
@@ -905,9 +911,9 @@
 Vivek Galatage <vivek.vg@samsung.com>
 Volker Sorge <volker.sorge@gmail.com>
 Waihung Fu <fufranci@amazon.com>
+Wanming Lin <wanming.lin@intel.com>
 WenSheng He <wensheng.he@samsung.com>
 Wesley Lancel <wesleylancel@gmail.com>
-Wesley Wigham <t-weswig@microsoft.com>
 Wesley Wigham <wwigham@gmail.com>
 Will Hirsch <chromium@willhirsch.co.uk>
 Will Shackleton <w.shackleton@gmail.com>
@@ -981,7 +987,7 @@
 Rajesh Mahindra <rmahindra@uber.com>
 Yuan-Pin Yu <yjames@uber.com>
 Vinoth Chandar <vinoth@uber.com>
-Zheng Xu <zxu@kobo.com>

+Zheng Xu <zxu@kobo.com>
 
 ACCESS CO., LTD. <*@access-company.com>
 Akamai Inc. <*@akamai.com>
@@ -1008,6 +1014,7 @@
 LG Electronics, Inc. <*@lge.com>
 Loongson Technology Corporation Limited. <*@loongson.cn>
 Macadamian <*@macadamian.com>
+Microsoft <*@microsoft.com>
 MIPS Technologies, Inc. <*@mips.com>
 Mozilla Corporation <*@mozilla.com>
 Neverware Inc. <*@neverware.com>
@@ -1029,3 +1036,4 @@
 Vewd Software AS <*@vewd.com>
 Vivaldi Technologies AS <*@vivaldi.com>
 Yandex LLC <*@yandex-team.ru>
+Make Positive Provar Limited <*@provartesting.com>
diff --git a/BUILD.gn b/BUILD.gn
index dbe4b22..59d65aa 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -115,7 +115,6 @@
       "//ppapi/examples/2d",
       "//ppapi/examples/audio",
       "//ppapi/examples/audio_input",
-      "//ppapi/examples/compositor",
       "//ppapi/examples/crxfs",
       "//ppapi/examples/enumerate_devices",
       "//ppapi/examples/file_chooser",
@@ -143,8 +142,8 @@
       "//third_party/SPIRV-Tools/src:SPIRV-Tools",
       "//third_party/SPIRV-Tools/src/test/fuzzers",
       "//third_party/cacheinvalidation:cacheinvalidation_unittests",
-      "//third_party/dawn:dawn_end2end_tests",
-      "//third_party/dawn:dawn_unittests",
+      "//third_party/dawn:dawn_end2end_tests_temp_group",
+      "//third_party/dawn:dawn_unittests_temp_group",
       "//third_party/pdfium/samples:pdfium_test",
       "//third_party/webrtc/rtc_tools:frame_analyzer",
       "//tools/perf/clear_system_cache",
@@ -188,7 +187,7 @@
       "//chrome/test:telemetry_perf_unittests",
       "//chrome/test:unit_tests",
       "//components:components_browsertests",
-      "//components/ui_devtools/viz_views",
+      "//components/ui_devtools/viz",
       "//components/viz:viz_perftests",
       "//components/viz:viz_unittests",
       "//components/viz/common:viz_benchmark",
@@ -334,7 +333,6 @@
         "//components/cronet/android:cronet_perf_test_apk",
         "//components/cronet/android:cronet_sample_apk",
         "//components/cronet/android:cronet_sample_test_apk",
-        "//components/cronet/android:cronet_test_apk",
         "//components/cronet/android:cronet_test_instrumentation_apk",
         "//components/cronet/android:cronet_unittests_android",
       ]
@@ -395,7 +393,6 @@
 
   if (is_chromeos) {
     deps += [
-      "//ash:ash_content_unittests",
       "//ash:ash_shell_with_content",
       "//ash:ash_unittests",
       "//ash/app_list:app_list_demo",
@@ -666,11 +663,11 @@
     }
   }
 
-  if (is_mac || is_linux || is_android) {
+  if (is_mac || is_linux || is_android || is_fuchsia) {
     deps += [ "//third_party/perfetto:all" ]
   }
 
-  if (is_mac || is_linux) {
+  if (is_win || is_mac || is_linux) {
     deps += [ "//third_party/sqlite:sqlite_shell" ]
   }
 
@@ -980,11 +977,12 @@
       ":layout_test_data_mojo_bindings",
       ":layout_test_data_mojo_bindings_lite",
       "//content/shell:content_shell",
-      "//content/test:mojo_layouttest_bindings_js_data_deps",
+      "//content/test:mojo_web_test_bindings_js_data_deps",
       "//device/bluetooth/public/mojom:fake_bluetooth_interfaces_js_data_deps",
       "//device/usb/public/mojom:mojom_js_data_deps",
       "//device/vr/public/mojom:mojom_js_data_deps",
       "//media/capture/mojom:image_capture_js_data_deps",
+      "//media/midi:mojo_js_data_deps",
       "//mojo/public/interfaces/bindings/tests:test_data_deps",
       "//mojo/public/mojom/base:base_js_data_deps",
       "//services/shape_detection/public/mojom:mojom_js_data_deps",
@@ -1030,7 +1028,6 @@
     }
 
     data = [
-      "$root_build_dir/resources/inspector/",
       "//testing/scripts/common.py",
       "//testing/scripts/run_isolated_script_test.py",
       "//testing/xvfb.py",
@@ -1188,10 +1185,7 @@
       ]
     }
     if (enable_ipc_fuzzer && !is_component_build) {
-      deps += [
-        "//chrome/app:service_manifests",
-        "//tools/ipc_fuzzer:ipc_fuzzer_all",
-      ]
+      deps += [ "//tools/ipc_fuzzer:ipc_fuzzer_all" ]
     }
     if (!is_chromeos) {
       deps += [
diff --git a/DEPS b/DEPS
index 7ebf90b..5f778ca 100644
--- a/DEPS
+++ b/DEPS
@@ -61,6 +61,12 @@
   # e.g. with custom_vars.
   'checkout_android_sdk_sources': False,
 
+  # By default, do not check out Chromium autofill captured sites test
+  # dependencies. These dependencies include very large numbers of very
+  # large web capture files. Captured sites test dependencies are also
+  # restricted to Googlers only.
+  'checkout_chromium_autofill_test_dependencies': False,
+
   # Check out and download nacl by default. This can be disabled e.g. with
   # custom_vars.
   'checkout_nacl': True,
@@ -82,9 +88,8 @@
   # By default do not check out the Oculus SDK. Only available for Googlers.
   'checkout_oculus_sdk' : 'checkout_src_internal and checkout_win',
 
-  # TODO(dpranke): change to != "small" once != is supported.
-  'checkout_traffic_annotation_tools': 'checkout_configuration == "default"',
-  'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"',
+  'checkout_traffic_annotation_tools': 'checkout_configuration != "small"',
+  'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration != "small"',
 
   # Default to the empty board. Desktop Chrome OS builds don't need cros SDK
   # dependencies. Other Chrome OS builds should always define this explicitly.
@@ -96,55 +101,59 @@
   # ANGLE's deps are relative to the angle_root variable.
   'angle_root': 'src/third_party/angle',
 
+  # luci-go CIPD package version.
+  'luci_go': 'git_revision:25958d48e89e980e2a97daeddc977fb5e2e1fb8c',
+
   'android_git': 'https://android.googlesource.com',
   'aomedia_git': 'https://aomedia.googlesource.com',
   'boringssl_git': 'https://boringssl.googlesource.com',
   'chromium_git': 'https://chromium.googlesource.com',
   'dawn_git': 'https://dawn.googlesource.com',
   'pdfium_git': 'https://pdfium.googlesource.com',
+  'quiche_git': 'https://quiche.googlesource.com',
   'skia_git': 'https://skia.googlesource.com',
   'swiftshader_git': 'https://swiftshader.googlesource.com',
   'webrtc_git': 'https://webrtc.googlesource.com',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling sfntly
   # and whatever else without interference from each other.
-  'sfntly_revision': 'b55ff303ea2f9e26702b514cf6a3196a2e3e2974',
+  'sfntly_revision': 'e24c73130c663c9f329e78f5ca3fd5bd83b02622',
   # 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': 'e6305f38b584ac51368a98de6a76d3f3205c21bf',
+  'skia_revision': 'cb42fc0dc56fd7fd7e0f9584b49f7f1870e0275b',
   # 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': '6acd03c9b8a8232aee95f25fbf6ae822aaedae75',
+  'v8_revision': '1dbc85c831e45a2ea1975da31809faab23c65593',
   # 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.
-  'swarming_revision': '157bec8a25cc4ebd6a16052510d08b05b6102aad',
+  'swarming_revision': '0e3e1c4dc4e79f25a5b58fcbc135dc93183c0c54',
   # 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': '5f01324fb627a502823d9e359d243c3430920258',
+  'angle_revision': '18af9a5a50c69c72a08fcad31bd94b56b05b4834',
   # 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.
-  'buildtools_revision': '04161ec8d7c781e4498c699254c69ba0dd959fde',
+  'buildtools_revision': '0e1cbc4eab6861b0c84bf2ed9a3c4b7aa2063819',
   # 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': '8f20452b0219dece19a9875bd11c04437a7e3cd4',
+  'swiftshader_revision': 'f8374cf0e75c0b44782ce903622a9fed1a1d709e',
   # 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': 'c3daaa87ec17c6e91de95fcaa1b5d255a0d7f978',
+  'pdfium_revision': 'ef92f656a86ef6c5b9493e325d2ae9bf2a624ca7',
   # 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.
-  'openmax_dl_revision': '59265e0e9105ec94e473b59c5c7ca1941e4dbd83',
+  'openmax_dl_revision': '3b18bf8338abbb9cc0dd5de4c69609c38eee9c8b',
   # 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': '0f5ecd3a854546d943104e1f7421e489b7f4d5aa',
+  'boringssl_revision': '8e8f250422663106d478f6927beefba289a95b37',
   # 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.
@@ -160,19 +169,19 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': 'f701a90597fc85979319447c0cd44c3b52201c78',
+  'nacl_revision': '1ea07c56ac9b57c30eb784ab2af582af0cdd4b08',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '3dd4e76b19f3cd4f706c3455d6ae01765d07eee5',
+  'freetype_revision': 'd01e28f41f8810c8ea422b854f8722659589fa99',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling HarfBuzz
   # and whatever else without interference from each other.
-  'harfbuzz_revision': '574d888c8a409295a952361a39c8e83a52a0fc3d',
+  'harfbuzz_revision': '26c5b54fb09fb45e02c9c4618bcea4958c698953',
   # 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': 'eee0f6ad0df532b4ba3eee2bf04a5a155817586c',
+  'catapult_revision': 'a24a725f7834c16b3628bfb63f349b3480bf9592',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -188,43 +197,43 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'feed_revision': '23d32902a8bd6f4d55dea6a46fff43325c61b532',
+  'feed_revision': '45d963c29e87258796293589f724ac08dab37cd0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_build-tools_version
   # and whatever else without interference from each other.
-  'android_sdk_build-tools_version': 'version:27.0.3-cr0',
+  'android_sdk_build-tools_version': '125a2abaa0393cd68a2414ec79e514d5d0a80b58',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_emulator_version
   # and whatever else without interference from each other.
-  'android_sdk_emulator_version': 'version:27.1.12-cr0',
+  'android_sdk_emulator_version': '731059df93885359487fd9d6085bc7804a23f9c8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_extras_version
   # and whatever else without interference from each other.
-  'android_sdk_extras_version': 'version:47.0.0-cr0',
+  'android_sdk_extras_version': '2f33032ef348e2ff37d90d53563f4cb030a879bf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_platform-tools_version
   # and whatever else without interference from each other.
-  'android_sdk_platform-tools_version': 'version:27.0.1-cr0',
+  'android_sdk_platform-tools_version': 'nVZAgkiZjKzmtiTSu70dJWaxpN4NzrPbfsGP7FjCe9UC',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_platforms_version
   # and whatever else without interference from each other.
-  'android_sdk_platforms_version': 'version:android-27-cr0',
+  'android_sdk_platforms_version': '6a79b931523181e147ddfc7db318bf0b2e34edb5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_sources_version
   # and whatever else without interference from each other.
-  'android_sdk_sources_version': 'version:android-27-cr1',
+  'android_sdk_sources_version': '8d8bd74d8f062449b8c44a663cc38a33ddf96752',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_tools_version
   # and whatever else without interference from each other.
-  'android_sdk_tools_version': 'version:26.1.1-cr9',
+  'android_sdk_tools_version': '1a659d51804abb9461cd19aeffc2102e47a15a25',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '3ee605d7ccb960345a454bad57e54238c66bfb05',
+  'spv_tools_revision': 'df5bd2d05ac1fd3ec3024439f885ec21cc949b22',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_headers_revision': 'bbf63435c37aafac5d1cdfc287401d87cd3ca364',
+  'spv_headers_revision': '79b6681aadcb53c27d1052e5f8a0e82a981dbf2f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -236,7 +245,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '813bfbd061128113dd7b4c7c80321b536597c362',
+  'dawn_revision': 'ec18f9683c28a5a65e36a5c53231d967dbfd4ee9',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling feed
+  # and whatever else without interference from each other.
+  'quiche_revision': '23346476fcb2863ac208b4e99edfd7a3aa6d3bcd',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -250,6 +263,7 @@
   'chromium.googlesource.com',
   'dawn.googlesource.com',
   'pdfium.googlesource.com',
+  'quiche.googlesource.com',
   'skia.googlesource.com',
   'swiftshader.googlesource.com',
   'webrtc.googlesource.com',
@@ -263,7 +277,7 @@
       'packages': [
           {
               'package': 'chromium/android_webview/tools/cts_archive',
-              'version': 'version:1.1',
+              'version': '3JR1LoM5xpNK_jcnwciobRW9H8TM3SUxuSGQJBjt6AUC',
           },
       ],
       'condition': 'checkout_android',
@@ -278,6 +292,17 @@
       'condition': 'checkout_mac',
   },
 
+  'src/chrome/test/data/autofill/captured_sites': {
+    'packages': [
+      {
+        'package': 'chromium/chrome/test/data/autofill/captured_sites',
+        'version': 'iTTirmwddgzWZrhbBLyYSUn-PFZNRIm5NjY9eYBgk0cC',
+      }
+    ],
+    'condition': 'checkout_chromium_autofill_test_dependencies',
+    'dep_type': 'cipd',
+  },
+
   'src/chrome/test/data/perf/canvas_bench':
     Var('chromium_git') + '/chromium/canvas_bench.git' + '@' + 'a7b40ea5ae0239517d78845a5fc9b12976bfc732',
 
@@ -288,7 +313,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/safe_browsing/dmg',
-        'version': 'version:20180816.2',
+        'version': 'a543ae3f0b3e67dd5a1c75f63317231a1d242912',
       },
     ],
     'condition': 'checkout_mac',
@@ -302,7 +327,7 @@
     Var('chromium_git') + '/external/github.com/immersive-web/webxr-samples.git' + '@' + 'cf02f19c4ff6894705a9407722ab52551e010c60',
 
   'src/ios/third_party/earl_grey/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '3102ef3b137f05a179628b1b9768856e5feea90e',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '25fc49c5e57b8d25e4011efdd6a96024d3e6b96e',
       'condition': 'checkout_ios',
   },
 
@@ -325,7 +350,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/firebase_ios',
-          'version': 'version:5.8.0',
+          'version': 'b44315eefb889f856af131d487cc61b46a78777b',
         },
       ],
       'condition': 'checkout_ios',
@@ -343,7 +368,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '6edafbda8131badfe6c57d4bb326071939a9713a',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '78a3b56667539a258782ed2da4d74d66fdd2295b',
       'condition': 'checkout_ios',
   },
 
@@ -353,7 +378,7 @@
   },
 
   'src/ios/third_party/material_internationalization_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-foundation/material-internationalization-ios.git' + '@' + 'c62f2cacaba48f8901ad811f23c2cbc9581364aa',
+      'url': Var('chromium_git') + '/external/github.com/material-foundation/material-internationalization-ios.git' + '@' + 'd8f32464ac97d5551c8db19de916170ae87cfa90',
       'condition': 'checkout_ios',
   },
 
@@ -368,22 +393,22 @@
   },
 
   'src/ios/third_party/material_text_accessibility_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-foundation/material-text-accessibility-ios.git' + '@' + '92c9e56f4e07622084b3d931247db974fec55dde',
+      'url': Var('chromium_git') + '/external/github.com/material-foundation/material-text-accessibility-ios.git' + '@' + '499b45d1895b565096302a209c0c728df03b95d4',
       'condition': 'checkout_ios',
   },
 
   'src/ios/third_party/motion_interchange_objc/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-interchange-objc.git' + '@' + '9be1e8572f8debb8dd9033ce9bd6ae56dc7ae1ab',
+      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-interchange-objc.git' + '@' + '6c385396ae7d3ee6752c3d625e322138eb8e25fc',
       'condition': 'checkout_ios',
   },
 
   'src/ios/third_party/motion_animator_objc/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-animator-objc.git' + '@' + '5df831026445004b2fc0f6a42f8b8f33af46512b',
+      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-animator-objc.git' + '@' + 'd300ae8ac3131b5ffde017ee2c1747bcc126e647',
       'condition': 'checkout_ios',
   },
 
   'src/ios/third_party/motion_transitioning_objc/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-transitioning-objc.git' + '@' + '994fd02d1de3d80ed284f0c1a4b5f459b8b051a6',
+      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-transitioning-objc.git' + '@' + '78ac32badf9ca9c1ad497a6131ce2bd539094812',
       'condition': 'checkout_ios',
   },
 
@@ -400,19 +425,22 @@
       'condition': 'checkout_nacl',
   },
 
+  'src/net/third_party/quiche/src':
+    Var('quiche_git') + '/quiche.git' + '@' +  Var('quiche_revision'),
+
   'src/tools/luci-go': {
       'packages': [
         {
           'package': 'infra/tools/luci/isolate/${{platform}}',
-          'version': 'git_revision:f140d0c3c6acecf6ca6cd8d66ddad9421158ab40',
+          'version': Var('luci_go'),
         },
         {
           'package': 'infra/tools/luci/isolated/${{platform}}',
-          'version': 'git_revision:f140d0c3c6acecf6ca6cd8d66ddad9421158ab40',
+          'version': Var('luci_go'),
         },
         {
           'package': 'infra/tools/luci/swarming/${{platform}}',
-          'version': 'git_revision:f140d0c3c6acecf6ca6cd8d66ddad9421158ab40',
+          'version': Var('luci_go'),
         },
       ],
       'dep_type': 'cipd',
@@ -442,7 +470,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/accessibility-test-framework',
-              'version': 'version:2.1-cr0',
+              'version': 'b5ec1e56e58e56bc1a0c77d43111c37f9b512c8a',
           },
       ],
       'condition': 'checkout_android',
@@ -463,7 +491,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_support_test_runner',
-              'version': 'version:0.5-cr0',
+              'version': '96d4bf848cd210fdcbca6bcc8c1b4b39cbd93141',
           },
       ],
       'condition': 'checkout_android',
@@ -474,7 +502,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_system_sdk',
-              'version': 'version:28-dp3-cr0',
+              'version': '0c0a94a9326c045c8aabb7fc418ea9c849b782f2',
           },
       ],
       'condition': 'checkout_android',
@@ -482,7 +510,7 @@
   },
 
   'src/third_party/android_tools': {
-      'url': Var('chromium_git') + '/android_tools.git' + '@' + '6fecaa542f73dd5aeed170d9a4cf340159b42976',
+      'url': Var('chromium_git') + '/android_tools.git' + '@' + 'e958d6ea74442d4e0849bb8a018d215a0e78981d',
       'condition': 'checkout_android_native_support',
   },
 
@@ -490,7 +518,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_build_tools/aapt2',
-              'version': 'version:3.3.0-beta01-5013011-cr0',
+              'version': 'XPNW95mgY7ws_5lNsyjlq7DowuughMNsRIGuGCT0basC',
           },
       ],
       'condition': 'checkout_android',
@@ -512,7 +540,7 @@
       'packages': [
           {
        'package': 'chromium/third_party/android_tools_bundletool',
-       'version': 'version:0.7.1-cr0',
+       'version': 'iBp9dwYQET2-P96y1HPJikezjXIprC6C4i6vUyviPcUC',
    },
       ],
       'condition': 'checkout_android',
@@ -579,7 +607,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/apk-patch-size-estimator',
-              'version': 'version:0.2-cr0',
+              'version': 'b603e99dca9b90d6a99519c232cd811878283b08',
           },
       ],
       'condition': 'checkout_android',
@@ -595,7 +623,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/bazel',
-              'version': 'version:0.10.0',
+              'version': '1794576f65a721eb0af320a0701e48d31f1b2415',
           },
       ],
       'condition': 'checkout_android',
@@ -617,7 +645,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/bouncycastle',
-              'version': 'version:1.46-cr0',
+              'version': 'c078e87552ba26e776566fdaf0f22cd8712743d0',
           },
       ],
       'condition': 'checkout_android',
@@ -631,7 +659,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/byte_buddy',
-              'version': 'version:1.8.8-cr0',
+              'version': 'c9b53316603fc2d997c899c7ca1707f809b918cd',
           },
       ],
       'condition': 'checkout_android',
@@ -642,7 +670,7 @@
     Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
 
   'src/third_party/cct_dynamic_module/src': {
-      'url': Var('chromium_git') + '/dynamicmodule' + '@' + 'b5a34248be7ff38ef4d7836123f3c796dfb18225',
+      'url': Var('chromium_git') + '/dynamicmodule' + '@' + '4c0a460459bc34177d3a71d6b49e253476431ec9',
       'condition': 'checkout_android',
   },
 
@@ -651,7 +679,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '81cbcd45e1a28db58d86bb556e1c40a289f35ef9',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9e5c9014937e8e477f42b0de84e17a1399276221',
       'condition': 'checkout_linux',
   },
 
@@ -666,7 +694,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'eb9630f2312fe23c4b9678f666ff45c3c6df949c',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'ea44d5db9e74027d28ef383156c754627a68dfe1',
       'condition': 'checkout_linux',
   },
 
@@ -676,7 +704,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9af233a5084871843af872224e4012e3f3f3af2f',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '36248fcd635b13c751d11e6722072bed2d57cb8a',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -698,7 +726,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/espresso',
-              'version': 'version:2.2.1-cr0',
+              'version': 'c92dcfc4e894555a0b3c309f2b7939640eb1fee4',
           },
       ],
       'condition': 'checkout_android',
@@ -711,7 +739,7 @@
   },
 
   'src/third_party/ffmpeg':
-    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '81f7d1dd5fa4ff50d9a8cd86e7b76796c056459d',
+    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '42bb040dde0a5e1bdb4b6d91f54297e0cc7f0977',
 
   'src/third_party/flac':
     Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
@@ -749,7 +777,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/google-truth',
-              'version': 'version:0.40',
+              'version': '4d6fe892fc3150ab40ef1d619baf0038859eb6d2',
           },
       ],
       'condition': 'checkout_android',
@@ -774,7 +802,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/gson',
-              'version': 'version:2.8.0-cr0',
+              'version': '681931c9778045903a0ed59856ce2dd8dd7bf7ca',
           },
       ],
       'condition': 'checkout_android',
@@ -785,7 +813,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/guava',
-              'version': 'version:23.0-cr0',
+              'version': 'a6fba501f3a0de88b9be1daa2052632de5b96a46',
           },
       ],
       'condition': 'checkout_android',
@@ -798,7 +826,7 @@
   },
 
   'src/third_party/arcore-android-sdk/src': {
-      'url': Var('chromium_git') + '/external/github.com/google-ar/arcore-android-sdk.git' + '@' + '772bed8e2e1bc525a0d10441fa71168a9a87eb69',
+      'url': Var('chromium_git') + '/external/github.com/google-ar/arcore-android-sdk.git' + '@' + '25b4589b55c02344cee5fd5722b06202c8b8776d',
       'condition': 'checkout_android',
   },
 
@@ -806,7 +834,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/hamcrest',
-              'version': 'version:1.3-cr0',
+              'version': '37eccfc658fe79695d6abb6dd497463c4372032f',
           },
       ],
       'condition': 'checkout_android',
@@ -817,13 +845,13 @@
     Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'a9bac57ce6c9d390a52ebaad3259f5fdb871210e',
 
   'src/third_party/icu':
-    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '407b39301e71006b68bd38e770f35d32398a7b14',
+    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'd65301491c513d49163ad29c853eb85c02c8d5b4',
 
   'src/third_party/icu4j': {
       'packages': [
           {
               'package': 'chromium/third_party/icu4j',
-              'version': 'version:53.1-cr0',
+              'version': 'e87e5bed2b4935913ee26a3ebd0b723ee2344354',
           },
       ],
       'condition': 'checkout_android',
@@ -834,7 +862,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/intellij',
-              'version': 'version:12.0-cr0',
+              'version': '77c2721b024b36ee073402c08e6d8428c0295336',
           },
       ],
       'condition': 'checkout_android',
@@ -855,7 +883,7 @@
   },
 
   'src/third_party/leveldatabase/src':
-    Var('chromium_git') + '/external/leveldb.git' + '@' + '73d5834eceee8efa9a8ccfec77dc096a9e8ba18a',
+    Var('chromium_git') + '/external/leveldb.git' + '@' + 'b70493ca8586285b49e9888e2b528f71806bdc6e',
 
   'src/third_party/libFuzzer/src':
     Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' +  Var('libfuzzer_revision'),
@@ -864,7 +892,7 @@
     Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'd7ed8e2f3f35ce9a3aafdfdc48745ceab66e7229',
 
   'src/third_party/libaom/source/libaom':
-    Var('aomedia_git') + '/aom.git' + '@' +  '67223a304e098da309776bac253456f75f613fc2',
+    Var('aomedia_git') + '/aom.git' + '@' +  '20a747b9ce5ec99ad2f78dd206a3fc1b8abf6850',
 
   # Userspace interface to kernel DRM services.
   'src/third_party/libdrm/src': {
@@ -882,7 +910,7 @@
     Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '61a2bbaa9aec89cb2c882d87ace6aba9aee49bb9',
 
   'src/third_party/liblouis/src': {
-      'url': Var('chromium_git') + '/external/liblouis-github.git' + '@' + '5f9c03f2a3478561deb6ae4798175094be8a26c2',
+      'url': Var('chromium_git') + '/external/liblouis-github.git' + '@' + '97ce1c67fccbd3668291b7e63c06161c095d49f2',
       'condition': 'checkout_linux',
   },
 
@@ -902,7 +930,7 @@
   },
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '615922dfb53103aa3d1620790b97d2ba3b4c76ad',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '57f7c6f19144786c57d5cfc8e878765bd9944baf',
 
   'src/third_party/libwebm/source':
     Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4931ebc0a816458c18a6734e91a4d1b5acd5c56',
@@ -940,7 +968,7 @@
 
   # Minizip library. Used on Chrome OS.
   'src/third_party/minizip/src': {
-      'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + '4d4c9db5b019e71b4a40fb41ab21fb47de12ae69',
+      'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + '1ff40343b55e738d941abb51c70eddb803db16e2',
       'condition': 'checkout_linux',
   },
 
@@ -974,7 +1002,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/objenesis',
-              'version': 'version:2.4-cr0',
+              'version': '9e367f55e5a65781ee77bfcbaa88fb82b30e75c0',
           },
       ],
       'condition': 'checkout_android',
@@ -982,7 +1010,7 @@
   },
 
   'src/third_party/openh264/src':
-    Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3b51f16a4a41df729f8d647f03e48c5f272911ff',
+    Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '6f26bce0b1c4e8ce0e13332f7c0083788def5fdf',
 
   'src/third_party/openmax_dl':
     Var('webrtc_git') + '/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
@@ -991,7 +1019,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/ow2_asm',
-              'version': 'version:5.0.1-cr0',
+              'version': '0dcaea8bd839b3f2eb8415c327b40e8e398a373e',
           },
       ],
       'condition': 'checkout_android',
@@ -1008,7 +1036,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '7b49412a6e09da8fe1d37dca67db94c12a509ffc',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'f7793ef4be2e63f5dcabba430b6bb128d68c1c0a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1075,13 +1103,13 @@
   },
 
   'src/third_party/re2/src':
-    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '749d64c35e09849045303c3de4e9955597b75b53',
+    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '2cf86e5ab6dcfe045a1f510c2b9a8b012a4158cd',
 
   'src/third_party/r8': {
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'uM1IGlYVeBYwmhwRCSMVqRvmu4YFlL7M2yLwZ1DWUvAC',
+              'version': 'D9fqCyfGhC3zMZFOE-4gzA0yox519Qd-DRgqnkqJuqgC',
           },
       ],
       'condition': 'checkout_android',
@@ -1119,13 +1147,13 @@
     Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f',
 
   'src/third_party/snappy/src':
-    Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + 'ea660b57d65d68d521287c903459b6dd3b2804d0',
+    Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + '3f194acb57e0487531c96b97af61dcbd025a78a3',
 
   'src/third_party/sqlite4java': {
       'packages': [
           {
               'package': 'chromium/third_party/sqlite4java',
-              'version': 'version:0.282-cr0',
+              'version': '889660698187baa7c8b0d79f7bf58563125fbd66',
           },
       ],
       'condition': 'checkout_android',
@@ -1168,10 +1196,10 @@
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/webgl/src':
-    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5b6cbd789b9b91b4e46dde883c9f2ecb31eddade',
+    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'f22b9ad8d75bf99652dfc3b1db40e73d9fdd3840',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '0d007d7c4f11414bb4f0712cb53f7eea4a1b0795',
+    Var('webrtc_git') + '/src.git' + '@' + '87da937789aeb91e694ecbba436c0f4b44461218',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1182,7 +1210,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/xstream',
-              'version': 'version:1.4.8-cr0',
+              'version': '4278b1b78b86ab7a1a29e64d5aec9a47a9aab0fe',
           },
       ],
       'condition': 'checkout_android',
@@ -1195,6 +1223,16 @@
   'src/tools/page_cycler/acid3':
     Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
 
+  'src/tools/skia_goldctl': {
+      'packages': [
+        {
+          'package': 'skia/tools/goldctl/${{platform}}',
+          'version': 'git_revision:21cbe1f4cc524c5d54d563951bc4c0687d57a8e7',
+        },
+      ],
+      'dep_type': 'cipd',
+  },
+
   'src/tools/swarming_client':
     Var('chromium_git') + '/infra/luci/client-py.git' + '@' +  Var('swarming_revision'),
 
@@ -1202,7 +1240,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f9b825600fd5a15c59671bb4fe92037c544ab7a7',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2d0af955521159f296615b24f6d9c5e402e5d100',
     'condition': 'checkout_src_internal',
   },
 
@@ -1210,7 +1248,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_deps/libs/com_google_android_play_core_verification',
-              'version': 'version:1.3.7-cr0',
+              'version': 'CMX_sCQTYt-Pj3-xFaCMPNGK3TjVMfToP2glkNm1a4AC',
           },
       ],
       'condition': 'checkout_android',
@@ -1725,6 +1763,17 @@
       'dep_type': 'cipd',
   },
 
+  'src/third_party/android_deps/libs/com_google_ar_core': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/android_deps/libs/com_google_ar_core',
+              'version': 'version:1.5.0-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/android_deps/libs/com_google_code_findbugs_jsr305': {
       'packages': [
           {
@@ -1978,7 +2027,6 @@
         'src/third_party/blink/tools',  # See http://crbug.com/625877.
         'src/third_party/catapult',
         'src/third_party/closure_compiler/build',
-        'src/third_party/WebKit/Tools/Scripts',  # See http://crbug.com/625877.
         'src/tools',
     ],
   },
@@ -2505,7 +2553,7 @@
     ],
   },
   {
-    'name': 'gvr_static_shim_android_arm',
+    'name': 'gvr_static_shim_android_arm_1',
     'pattern': '\\.sha1',
     'condition': 'checkout_android',
     'action': [ 'python',
@@ -2513,11 +2561,11 @@
                 '--no_resume',
                 '--no_auth',
                 '--bucket', 'chromium-gvr-static-shim',
-                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm.a.sha1',
+                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm_1.a.sha1',
     ],
   },
   {
-    'name': 'gvr_static_shim_android_arm64',
+    'name': 'gvr_static_shim_android_arm_ndk1',
     'pattern': '\\.sha1',
     'condition': 'checkout_android',
     'action': [ 'python',
@@ -2525,23 +2573,11 @@
                 '--no_resume',
                 '--no_auth',
                 '--bucket', 'chromium-gvr-static-shim',
-                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm64.a.sha1',
-      ],
-  },
-  {
-    'name': 'gvr_static_shim_custom_libcxx_android_arm',
-    'pattern': '\\.sha1',
-    'condition': 'checkout_android',
-    'action': [ 'python',
-                'src/third_party/depot_tools/download_from_google_storage.py',
-                '--no_resume',
-                '--no_auth',
-                '--bucket', 'chromium-gvr-static-shim',
-                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_custom_libcxx_arm.a.sha1',
+                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm_ndk1.a.sha1',
     ],
   },
   {
-    'name': 'gvr_static_shim_custom_libcxx_android_arm64',
+    'name': 'gvr_static_shim_android_arm_Cr',
     'pattern': '\\.sha1',
     'condition': 'checkout_android',
     'action': [ 'python',
@@ -2549,19 +2585,43 @@
                 '--no_resume',
                 '--no_auth',
                 '--bucket', 'chromium-gvr-static-shim',
-                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_custom_libcxx_arm64.a.sha1',
-      ],
+                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm_Cr.a.sha1',
+    ],
   },
   {
-    'name': 'vr_assets',
-    'pattern': '.',
-    'condition': 'checkout_src_internal and checkout_android',
-    'action': ['python',
-               'src/third_party/depot_tools/download_from_google_storage.py',
-               '--bucket', 'chrome-vr-assets',
-               '--recursive',
-               '--directory',
-               'src/chrome/browser/resources/vr/assets/google_chrome',
+    'name': 'gvr_static_shim_android_arm64_1',
+    'pattern': '\\.sha1',
+    'condition': 'checkout_android',
+    'action': [ 'python',
+                'src/third_party/depot_tools/download_from_google_storage.py',
+                '--no_resume',
+                '--no_auth',
+                '--bucket', 'chromium-gvr-static-shim',
+                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm64_1.a.sha1',
+    ],
+  },
+  {
+    'name': 'gvr_static_shim_android_arm64_ndk1',
+    'pattern': '\\.sha1',
+    'condition': 'checkout_android',
+    'action': [ 'python',
+                'src/third_party/depot_tools/download_from_google_storage.py',
+                '--no_resume',
+                '--no_auth',
+                '--bucket', 'chromium-gvr-static-shim',
+                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm64_ndk1.a.sha1',
+    ],
+  },
+  {
+    'name': 'gvr_static_shim_android_arm64_Cr',
+    'pattern': '\\.sha1',
+    'condition': 'checkout_android',
+    'action': [ 'python',
+                'src/third_party/depot_tools/download_from_google_storage.py',
+                '--no_resume',
+                '--no_auth',
+                '--bucket', 'chromium-gvr-static-shim',
+                '-s', 'src/third_party/gvr-android-sdk/libgvr_shim_static_arm64_Cr.a.sha1',
     ],
   },
   {
@@ -2608,6 +2668,34 @@
                'src/third_party/libovr/src',
     ],
   },
+  # Download ink resources for chromeos.
+  {
+    'name': 'ink-build',
+    'pattern': '.',
+    'condition': 'checkout_chromeos',
+    'action': [ 'python',
+                'src/third_party/depot_tools/download_from_google_storage.py',
+                '--no_resume',
+                '--no_auth',
+                '--num_threads=4',
+                '--bucket', 'chromium-ink',
+                '-d', 'src/third_party/ink/build',
+    ],
+  },
+  # Download ink resources for chromeos.
+  {
+    'name': 'ink-build-wasm',
+    'pattern': '.',
+    'condition': 'checkout_chromeos',
+    'action': [ 'python',
+                'src/third_party/depot_tools/download_from_google_storage.py',
+                '--no_resume',
+                '--no_auth',
+                '--num_threads=4',
+                '--bucket', 'chromium-ink',
+                '-d', 'src/third_party/ink/build/wasm',
+    ],
+  },
   {
     # Pull doclava binaries if building for Android.
     'name': 'doclava',
@@ -2640,6 +2728,7 @@
       'chrome-sdk',
       '--nogoma',
       '--use-external-config',
+      '--require-exact-version',
       '--nogn-gen',
       '--download-vm',
       '--board={cros_board}',
@@ -2661,6 +2750,7 @@
       'chrome-sdk',
       '--nogoma',
       '--use-external-config',
+      '--require-exact-version',
       '--nogn-gen',
       '--board={cros_board}',
       '--cache-dir=src/build/cros_cache/',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index c3db098..89967c3c 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -15,7 +15,7 @@
     r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk",
     r"^net[\\/]tools[\\/]spdyshark[\\/].*",
     r"^skia[\\/].*",
-    r"^third_party[\\/](WebKit|blink)[\\/].*",
+    r"^third_party[\\/]blink[\\/].*",
     r"^third_party[\\/]breakpad[\\/].*",
     r"^v8[\\/].*",
     r".*MakeFile$",
@@ -343,6 +343,7 @@
       ),
       True,
       (
+          r'^base[\\/]third_party[\\/]symbolize[\\/].*',
           r'^third_party[\\/]abseil-cpp[\\/].*',
       ),
     ),
@@ -565,15 +566,6 @@
       ),
     ),
     (
-      r'/\barraysize\b',
-      (
-          "arraysize is deprecated, please use base::size(array) instead ",
-          "(https://crbug.com/837308). ",
-      ),
-      False,
-      (),
-    ),
-    (
       r'std::random_shuffle',
       (
         'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
@@ -654,14 +646,12 @@
     'build/android/gyp/aar.pydeps',
     'build/android/gyp/aidl.pydeps',
     'build/android/gyp/apkbuilder.pydeps',
-    'build/android/gyp/app_bundle_to_apks.pydeps',
     'build/android/gyp/bytecode_processor.pydeps',
     'build/android/gyp/compile_resources.pydeps',
     'build/android/gyp/create_bundle_wrapper_script.pydeps',
     'build/android/gyp/copy_ex.pydeps',
     'build/android/gyp/create_app_bundle.pydeps',
     'build/android/gyp/create_apk_operations_script.pydeps',
-    'build/android/gyp/create_dist_jar.pydeps',
     'build/android/gyp/create_java_binary_script.pydeps',
     'build/android/gyp/create_stack_script.pydeps',
     'build/android/gyp/create_test_runner_script.pydeps',
@@ -686,6 +676,7 @@
     'build/android/gyp/proguard.pydeps',
     'build/android/gyp/write_build_config.pydeps',
     'build/android/gyp/write_ordered_libraries.pydeps',
+    'build/android/gyp/zip.pydeps',
     'build/android/incremental_install/generate_android_manifest.pydeps',
     'build/android/incremental_install/write_installer_json.pydeps',
     'build/android/resource_sizes.pydeps',
@@ -1551,7 +1542,7 @@
   virtual_depended_on_files = set()
 
   file_filter = lambda f: not input_api.re.match(
-      r"^third_party[\\/](WebKit|blink)[\\/].*", f.LocalPath())
+      r"^third_party[\\/]blink[\\/].*", f.LocalPath())
   for f in input_api.AffectedFiles(include_deletes=False,
                                    file_filter=file_filter):
     filename = input_api.os_path.basename(f.LocalPath())
@@ -2082,7 +2073,8 @@
   # *.mojom files.
   for f in input_api.AffectedFiles(include_deletes=False):
     # Manifest files don't have a strong naming convention. Instead, scan
-    # affected files for .json files and see if they look like a manifest.
+    # affected files for .json, .cc, and .h files which look like they contain
+    # a manifest definition.
     if (f.LocalPath().endswith('.json') and
         not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
                          f.LocalPath())):
@@ -2098,6 +2090,15 @@
         continue
       if 'interface_provider_specs' in json_content:
         AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
+    else:
+      manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
+      test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
+      if (manifest_pattern.search(f.LocalPath()) and not
+          test_manifest_pattern.search(f.LocalPath())):
+        # We expect all actual service manifest files to contain at least one
+        # qualified reference to service_manager::Manifest.
+        if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
+          AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
     for pattern in file_patterns:
       if input_api.fnmatch.fnmatch(
           input_api.os_path.basename(f.LocalPath()), pattern):
@@ -2178,9 +2179,7 @@
   for f in input_api.AffectedFiles(include_deletes=False):
     if (f.LocalPath().startswith('third_party') and
         not f.LocalPath().startswith('third_party/blink') and
-        not f.LocalPath().startswith('third_party\\blink') and
-        not f.LocalPath().startswith('third_party/WebKit') and
-        not f.LocalPath().startswith('third_party\\WebKit')):
+        not f.LocalPath().startswith('third_party\\blink')):
       continue
 
     if not f.LocalPath().endswith('.h'):
@@ -2492,6 +2491,24 @@
   return results
 
 
+def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
+  """Checks Android XML styles """
+  import sys
+  original_sys_path = sys.path
+  try:
+    sys.path = sys.path + [input_api.os_path.join(
+        input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
+    import checkxmlstyle
+  finally:
+    # Restore sys.path to what it was before.
+    sys.path = original_sys_path
+
+  if is_check_on_upload:
+    return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
+  else:
+    return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
+
+
 class PydepsChecker(object):
   def __init__(self, input_api, pydeps_files):
     self._file_cache = {}
@@ -2734,8 +2751,8 @@
   bad_files = {}
   for f in input_api.AffectedFiles(include_deletes=False):
     if (f.LocalPath().startswith('third_party') and
-      not f.LocalPath().startswith('third_party/WebKit') and
-      not f.LocalPath().startswith('third_party\\WebKit')):
+      not f.LocalPath().startswith('third_party/blink') and
+      not f.LocalPath().startswith('third_party\\blink')):
       continue
 
     if not CppChecker.IsCppFile(f.LocalPath()):
@@ -2987,7 +3004,7 @@
 
 
 def _AndroidSpecificOnUploadChecks(input_api, output_api):
-  """Groups checks that target android code."""
+  """Groups upload checks that target android code."""
   results = []
   results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
   results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
@@ -2996,6 +3013,13 @@
   results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
   results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
   results.extend(_CheckAndroidWebkitImports(input_api, output_api))
+  results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
+  return results
+
+def _AndroidSpecificOnCommitChecks(input_api, output_api):
+  """Groups commit checks that target android code."""
+  results = []
+  results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
   return results
 
 
@@ -3173,7 +3197,7 @@
 def _CheckForInvalidOSMacros(input_api, output_api):
   """Check all affected files for invalid OS macros."""
   bad_macros = []
-  for f in input_api.AffectedFiles():
+  for f in input_api.AffectedSourceFiles(None):
     if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
       bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
 
@@ -3474,6 +3498,7 @@
 def CheckChangeOnCommit(input_api, output_api):
   results = []
   results.extend(_CommonChecks(input_api, output_api))
+  results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
   # Make sure the tree is 'open'.
   results.extend(input_api.canned_checks.CheckTreeIsOpen(
       input_api,
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index a04f742..e3c16f6 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -1377,11 +1377,11 @@
   def testBlinkHeaders(self):
     mock_input_api = MockInputApi()
     mock_input_api.files = [
-      MockAffectedFile('third_party/WebKit/header.h', [
+      MockAffectedFile('third_party/blink/header.h', [
         'class DummyClass;',
         'struct DummyStruct;',
       ]),
-      MockAffectedFile('third_party\\WebKit\\header.h', [
+      MockAffectedFile('third_party\\blink\\header.h', [
         'class DummyClass;',
         'struct DummyStruct;',
       ])
@@ -1445,7 +1445,7 @@
   def testRelativeIncludeWebKitProducesError(self):
     mock_input_api = MockInputApi()
     mock_input_api.files = [
-      MockAffectedFile('third_party/WebKit/test.cpp',
+      MockAffectedFile('third_party/blink/test.cpp',
                        ['#include "../header.h']),
     ]
 
@@ -1682,8 +1682,8 @@
         'chrome/app/chromium_strings.grd:8' in warnings[1].items[1])
 
 
-class MojoManifestOwnerTest(unittest.TestCase):
-  def testMojoManifestChangeNeedsSecurityOwner(self):
+class ServiceManifestOwnerTest(unittest.TestCase):
+  def testServiceManifestJsonChangeNeedsSecurityOwner(self):
     mock_input_api = MockInputApi()
     mock_input_api.files = [
       MockAffectedFile('services/goat/manifest.json',
@@ -1706,7 +1706,7 @@
 
     # No warning if already covered by an OWNERS rule.
 
-  def testNonManifestChangesDoNotRequireSecurityOwner(self):
+  def testNonManifestJsonChangesDoNotRequireSecurityOwner(self):
     mock_input_api = MockInputApi()
     mock_input_api.files = [
       MockAffectedFile('services/goat/species.json',
@@ -1722,6 +1722,34 @@
         mock_input_api, mock_output_api)
     self.assertEqual([], errors)
 
+  def testServiceManifestChangeNeedsSecurityOwner(self):
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockAffectedFile('services/goat/public/cpp/manifest.cc',
+                       [
+                         '#include "services/goat/public/cpp/manifest.h"',
+                         'const service_manager::Manifest& GetManifest() {}',
+                       ])]
+    mock_output_api = MockOutputApi()
+    errors = PRESUBMIT._CheckIpcOwners(
+        mock_input_api, mock_output_api)
+    self.assertEqual(1, len(errors))
+    self.assertEqual(
+        'Found OWNERS files that need to be updated for IPC security review ' +
+        'coverage.\nPlease update the OWNERS files below:', errors[0].message)
+
+  def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockAffectedFile('some/non/service/thing/foo_manifest.cc',
+                       [
+                         'const char kNoEnforcement[] = "not a manifest!";',
+                       ])]
+    mock_output_api = MockOutputApi()
+    errors = PRESUBMIT._CheckIpcOwners(
+        mock_input_api, mock_output_api)
+    self.assertEqual([], errors)
+
 
 class BannedFunctionCheckTest(unittest.TestCase):
 
@@ -1996,9 +2024,10 @@
                                                       MockOutputApi())
     self.assertEqual(1, len(warnings))
     self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
-    self.assertEqual(
-      ['test_grd/IDS_TEST1.png.sha1', 'test_grd/IDS_TEST2.png.sha1'],
-      warnings[0].items)
+    self.assertEqual([
+        os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
+        os.path.join('test_grd', 'IDS_TEST2.png.sha1')
+    ], warnings[0].items)
 
     input_api = self.makeInputApi([
       MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
@@ -2007,46 +2036,72 @@
                                                       MockOutputApi())
     self.assertEqual(1, len(warnings))
     self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message)
-    self.assertEqual(['test_grd/IDS_TEST2.png.sha1'], warnings[0].items)
+    self.assertEqual([os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
+                     warnings[0].items)
 
 
   def testUnnecessaryScreenshots(self):
     # CL added a single message and added the png file, but not the sha1 file.
     input_api = self.makeInputApi([
-      MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS1,
-                       self.OLD_GRD_CONTENTS, action='M'),
-      MockAffectedFile('test_grd/IDS_TEST1.png', 'binary', action='A')])
+        MockAffectedFile(
+            'test.grd',
+            self.NEW_GRD_CONTENTS1,
+            self.OLD_GRD_CONTENTS,
+            action='M'),
+        MockAffectedFile(
+            os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
+    ])
     warnings = PRESUBMIT._CheckTranslationScreenshots(input_api,
                                                       MockOutputApi())
     self.assertEqual(2, len(warnings))
     self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
-    self.assertEqual(['test_grd/IDS_TEST1.png'], warnings[0].items)
+    self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
+                     warnings[0].items)
     self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
-    self.assertEqual(['test_grd/IDS_TEST1.png.sha1'], warnings[1].items)
+    self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
+                     warnings[1].items)
 
     # CL added two messages, one has a png. Expect two messages:
     # - One for the unnecessary png.
     # - Another one for missing .sha1 files.
     input_api = self.makeInputApi([
-      MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
-                       self.OLD_GRD_CONTENTS, action='M'),
-      MockAffectedFile('test_grd/IDS_TEST1.png', 'binary', action='A')])
+        MockAffectedFile(
+            'test.grd',
+            self.NEW_GRD_CONTENTS2,
+            self.OLD_GRD_CONTENTS,
+            action='M'),
+        MockAffectedFile(
+            os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A')
+    ])
     warnings = PRESUBMIT._CheckTranslationScreenshots(input_api,
                                                       MockOutputApi())
     self.assertEqual(2, len(warnings))
     self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
-    self.assertEqual(['test_grd/IDS_TEST1.png'], warnings[0].items)
+    self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png')],
+                     warnings[0].items)
     self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[1].message)
-    self.assertEqual(['test_grd/IDS_TEST1.png.sha1',
-                      'test_grd/IDS_TEST2.png.sha1'], warnings[1].items)
+    self.assertEqual([
+        os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
+        os.path.join('test_grd', 'IDS_TEST2.png.sha1')
+    ], warnings[1].items)
 
   def testScreenshotsWithSha1(self):
     # CL added two messages and their corresponding .sha1 files. No warnings.
     input_api = self.makeInputApi([
-      MockAffectedFile('test.grd', self.NEW_GRD_CONTENTS2,
-                       self.OLD_GRD_CONTENTS, action='M'),
-      MockFile('test_grd/IDS_TEST1.png.sha1', 'binary', action='A'),
-      MockFile('test_grd/IDS_TEST2.png.sha1', 'binary', action='A')])
+        MockAffectedFile(
+            'test.grd',
+            self.NEW_GRD_CONTENTS2,
+            self.OLD_GRD_CONTENTS,
+            action='M'),
+        MockFile(
+            os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
+            'binary',
+            action='A'),
+        MockFile(
+            os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
+            'binary',
+            action='A')
+    ])
     warnings = PRESUBMIT._CheckTranslationScreenshots(input_api,
                                                       MockOutputApi())
     self.assertEqual([], warnings)
@@ -2055,36 +2110,60 @@
     # Swap old contents with new contents, remove IDS_TEST1 and IDS_TEST2. The
     # sha1 files associated with the messages should also be removed by the CL.
     input_api = self.makeInputApi([
-      MockAffectedFile('test.grd', self.OLD_GRD_CONTENTS,
-                       self.NEW_GRD_CONTENTS2, action='M'),
-      MockFile('test_grd/IDS_TEST1.png.sha1', 'binary', ""),
-      MockFile('test_grd/IDS_TEST2.png.sha1', 'binary', "")])
+        MockAffectedFile(
+            'test.grd',
+            self.OLD_GRD_CONTENTS,
+            self.NEW_GRD_CONTENTS2,
+            action='M'),
+        MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ""),
+        MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', "")
+    ])
     warnings = PRESUBMIT._CheckTranslationScreenshots(input_api,
                                                       MockOutputApi())
     self.assertEqual(1, len(warnings))
     self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
-    self.assertEqual(['test_grd/IDS_TEST1.png.sha1',
-                      'test_grd/IDS_TEST2.png.sha1'], warnings[0].items)
+    self.assertEqual([
+        os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
+        os.path.join('test_grd', 'IDS_TEST2.png.sha1')
+    ], warnings[0].items)
 
     # Same as above, but this time one of the .sha1 files is removed.
     input_api = self.makeInputApi([
-      MockAffectedFile('test.grd', self.OLD_GRD_CONTENTS,
-                       self.NEW_GRD_CONTENTS2, action='M'),
-      MockFile('test_grd/IDS_TEST1.png.sha1', 'binary', ''),
-      MockAffectedFile('test_grd/IDS_TEST2.png.sha1',
-                       '', 'old_contents', action='D')])
+        MockAffectedFile(
+            'test.grd',
+            self.OLD_GRD_CONTENTS,
+            self.NEW_GRD_CONTENTS2,
+            action='M'),
+        MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
+        MockAffectedFile(
+            os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
+            '',
+            'old_contents',
+            action='D')
+    ])
     warnings = PRESUBMIT._CheckTranslationScreenshots(input_api,
                                                       MockOutputApi())
     self.assertEqual(1, len(warnings))
     self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
-    self.assertEqual(['test_grd/IDS_TEST1.png.sha1'], warnings[0].items)
+    self.assertEqual([os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
+                     warnings[0].items)
 
     # Remove both sha1 files. No presubmit warnings.
     input_api = self.makeInputApi([
-      MockAffectedFile('test.grd', self.OLD_GRD_CONTENTS,
-                       self.NEW_GRD_CONTENTS2, action='M'),
-      MockFile('test_grd/IDS_TEST1.png.sha1', 'binary', action='D'),
-      MockFile('test_grd/IDS_TEST2.png.sha1', 'binary', action='D')])
+        MockAffectedFile(
+            'test.grd',
+            self.OLD_GRD_CONTENTS,
+            self.NEW_GRD_CONTENTS2,
+            action='M'),
+        MockFile(
+            os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
+            'binary',
+            action='D'),
+        MockFile(
+            os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
+            'binary',
+            action='D')
+    ])
     warnings = PRESUBMIT._CheckTranslationScreenshots(input_api,
                                                       MockOutputApi())
     self.assertEqual([], warnings)
diff --git a/WATCHLISTS b/WATCHLISTS
index 8f2a55d..0dbc54f 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -61,9 +61,6 @@
     'android_lint': {
       'filepath': 'build/android/lint/'
     },
-    'android_loading': {
-      'filepath': 'tools/android/loading/'
-    },
     'android_media': {
       'filepath': 'content/browser/media/android' \
                   '|content/renderer/media/android' \
@@ -384,6 +381,11 @@
     'blink_htmlparser': {
       'filepath': 'third_party/blink/renderer/core/html/parser/'
     },
+    'blink_image_codecs': {
+      'filepath': 'third_party/blink/renderer/platform/image-decoders' \
+                  '|third_party/blink/renderer/platform/image-encoders' \
+                  '|third_party/blink/perf_tests/image_decoder'
+    },
     'blink_indexed_db': {
       'filepath': 'third_party/blink/common/indexeddb' \
                   '|third_party/blink/public/common/indexeddb' \
@@ -530,9 +532,6 @@
     'blink_spellcheck' : {
       'filepath': 'third_party/blink/renderer/core/editing/spellcheck'
     },
-    'blink_spv2_layout_tests': {
-      'filepath': 'third_party/blink/web_tests/virtual/spv2'
-    },
     'blink_streams': {
       'filepath': 'third_party/blink/renderer/core/streams/'
     },
@@ -780,6 +779,9 @@
     'components_deps': {
       'filepath': 'components/([^/]*/)*DEPS',
     },
+    'compositor_animator': {
+      'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/',
+    },
     'content_bluetooth': {
       'filepath': 'content/.*bluetooth'
     },
@@ -820,7 +822,12 @@
     },
     'custom_tabs': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/customtabs/|'\
-                  'chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/',
+                  'chrome/android/java/src/org/chromium/chrome/browser/browseractions/|'\
+                  'chrome/android/java/src/org/chromium/chrome/browser/browserservices/|'\
+                  'chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/|'\
+                  'chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/|'\
+                  'chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/|'\
+                  'chrome/browser/android/customtabs/',
     },
     'dbus': {
       'filepath': 'dbus/',
@@ -1046,6 +1053,11 @@
     'ios_clean': {
       'filepath': 'ios/clean/',
     },
+    'ios_flags': {
+      'filepath': 'ios/chrome/browser/about_flags\.(h|mm)|'\
+                  'ios/chrome/browser/experimental_flags\.(h|mm)|'\
+                  'ios/chrome/browser/resources/Settings.bundle/Experimental\.plist',
+    },
     'ios_showcase': {
       'filepath': 'ios/showcase/',
     },
@@ -1076,9 +1088,6 @@
     'linux_seccomp_bpf': {
       'filepath': 'content/common/sandbox.*linux.cc',
     },
-    'login': {
-      'filepath': 'chrome/browser/ui/login'
-    },
     'mac': {
       'filepath': '(_|/)(cocoa|mac)(_|\.)|/(cocoa|mac)/|^((?!ios\/).)*\.mm?$',
     },
@@ -1089,11 +1098,6 @@
     'mash_buildbot_filters': {
       'filepath': 'testing/buildbot/filters/mash.*filter',
     },
-    'md_settings': {
-      'filepath': 'chrome/browser/resources/settings/'\
-                  '|chrome/browser/ui/webui/settings/'\
-                  '|chrome/test/data/webui/settings/',
-    },
     'media': {
       'filepath': 'media|third_party/(ffmpeg|opus|libvpx)'
     },
@@ -1148,11 +1152,6 @@
     'media_win': {
       'filepath': 'media/gpu/windows/'
     },
-    'memory_coordinator': {
-      'filepath': 'base/memory/memory_|' \
-                  'content/browser/memory/|' \
-                  'content/child/memory/'
-    },
     'message_loop': {
       'filepath': 'base/message_'
     },
@@ -1183,6 +1182,7 @@
     },
     'multidevice': {
       'filepath': 'ash/multi_device_setup/'\
+                  '|chrome/browser/chromeos/cryptauth/'\
                   '|chrome/browser/chromeos/device_sync/'\
                   '|chrome/browser/chromeos/multidevice_setup/'\
                   '|chrome/browser/chromeos/secure_channel/'\
@@ -1190,11 +1190,13 @@
                   '|chrome/browser/resources/settings/multidevice_page/'\
                   '|chrome/browser/ui/webui/chromeos/multidevice_setup/'\
                   '|chrome/browser/ui/webui/settings/chromeos/multidevice'\
+                  '|chrome/test/data/webui/multidevice_setup/'\
+                  '|chromeos/components/multidevice/'\
                   '|chromeos/components/proximity_auth/'\
+                  '|chromeos/resources/multidevice_resources.grdp'\
                   '|chromeos/services/device_sync/'\
                   '|chromeos/services/multidevice_setup/'\
                   '|chromeos/services/secure_channel/'\
-                  '|components/cryptauth/'\
                   '|ui/webui/resources/cr_components/chromeos/multidevice_setup/'
     },
     'mus': {
@@ -1458,12 +1460,21 @@
                   '|components/cbor/'\
                   '|AndroidManifest',
     },
+    'send_tab_to_self': {
+      'filepath': 'components/send_tab_to_self' \
+        '|chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/',
+    },
     'service_worker': {
       'filepath': 'content/(browser|renderer|child|common)/service_worker/',
     },
     'services_public': {
       'filepath': 'services/([^/]*/)*public/',
     },
+    'settings': {
+      'filepath': 'chrome/browser/resources/settings/'\
+                  '|chrome/browser/ui/webui/settings/'\
+                  '|chrome/test/data/webui/settings/',
+    },
     'settings_reset_prompt': {
       'filepath': 'chrome/browser/safe_browsing/settings_reset_prompt/'\
                   '|chrome/browser/ui/views/settings_reset_prompt',
@@ -1517,6 +1528,11 @@
                   '|chrome/browser/.*managed_user'\
                   '|chrome/browser/.*supervised_user',
     },
+    'surface_layer_for_video': {
+      'filepath': 'cc/layers/surface_layer*'\
+                  '|third_party/blink/renderer/platform/graphics/video_frame_*'\
+                  '|third_party/blink/renderer/platform/graphics/surface_layer_bridge*',
+    },
     'sync': {
       'filepath': '^chrome/browser/ui/sync/'\
                   '|^chrome/browser/ui/views/sync/'\
@@ -1574,9 +1590,9 @@
     },
     'test_runner': {
       'filepath': 'components/test_runner/' \
-                  '|content/shell/(common|browser|renderer)/layout_test/' \
-                  '|content/test/layouttest_support.cc' \
-                  '|content/public/test/layouttest_support.h' \
+                  '|content/shell/(common|browser|renderer)/web_test/' \
+                  '|content/test/web_test_support.cc' \
+                  '|content/public/test/web_test_support.h' \
     },
     'tests': {
       'filepath': 'apitest|unittest|browsertest|uitest|chrome/test/',
@@ -1687,14 +1703,23 @@
       # Includes VR, AR, and XR.
       'filepath': '/vr/'\
                   '|/xr'\
+                  '|isolated_xr_device'\
                   '|third_party/arcore'\
                   '|third_party/gvr'\
                   '|third_party/libovr'\
                   '|third_party/openvr',
     },
+    'vulkan': {
+      'filepath': 'gpu/vulkan'\
+                  '|third_party/vulkan'
+    },
     'wake_lock': {
       'filepath': 'wake_lock',
     },
+    'web_dev_style': {
+      'filepath': 'tools/web_dev_style/'\
+                  '|styleguide/web/',
+    },
     'web_package': {
       'filepath': 'content/browser/loader/prefetch_url_loader'\
                   '|content/browser/web_package/'\
@@ -1734,6 +1759,11 @@
                   '|chrome/common/content_settings'\
                   '|components/content_settings/',
     },
+    'webui_backend': {
+      'filepath': 'content/browser/webui/'\
+                  '|content/public/browser/web_ui*'\
+                  '|content/public/test/*web_ui*',
+    },
     'windows_sandboxing': {
       'filepath': 'sandbox/win/',
     },
@@ -1746,6 +1776,9 @@
                   '|chrome/browser/chromeos/wm_' \
                   '|ui/base/x/'
     },
+    'zlib': {
+      'filepath': 'third_party/zlib'
+    },
     'zoom': {
       'filepath': 'chrome/browser/ui/zoom/' \
                   '|components/ui/zoom/' \
@@ -1787,8 +1820,6 @@
     'android_item_chooser_dialogs': ['juncai+watch@chromium.org',
                                      'ortuno+watch@chromium.org'],
     'android_lint': ['wnwen+watch@chromium.org'],
-    'android_loading': ['gabadie+watch@chromium.org',
-                        'lizeb+watch-android-loading@chromium.org'],
     'android_media': ['mlamouri+watch-media@chromium.org'],
     'android_search_widget': ['tedchoc+watch@chromium.org',
                               'yusufo+watch@chromium.org'],
@@ -1802,7 +1833,8 @@
     'animation_worklet': ['yigu@chromium.org',
                           'majidvp@chromium.org'],
     'app_list': ['tfarina@chromium.org'],
-    'app_shortcuts': ['loyso+watch@chromium.org',
+    'app_shortcuts': ['dominickn+watch-app_shortcuts@chromium.org',
+                      'loyso+watch@chromium.org',
                       'mgiuca+watch@chromium.org',
                       'tapted+watch@chromium.org'],
     'apps': ['chromium-apps-reviews@chromium.org',
@@ -1841,8 +1873,7 @@
                  'mathp+autofillwatch@chromium.org',
                  'rogerm+autofillwatch@chromium.org',
                  'sebsg+autofillwatch@chromium.org',
-                 'tmartino+autofillwatch@chromium.org',
-                 'vabr+watchlistautofill@chromium.org'],
+                 'tmartino+autofillwatch@chromium.org'],
     'autofill_assistant': ['autofill_assistant+watch@google.com'],
     'autofill_credit_cards': ['jsaul+autofillwatch@google.com'],
     'background_fetch': ['peter@chromium.org',
@@ -1935,6 +1966,7 @@
     'blink_html': ['blink-reviews-html@chromium.org'],
     'blink_htmlparser': ['kinuko+watch@chromium.org',
                          'loading-reviews+parser@chromium.org'],
+    'blink_image_codecs': ['cblume+imagecodecs@chromium.org'],
     'blink_indexed_db': ['cmumford@chromium.org',
                          'jsbell+idb@chromium.org'],
     'blink_input': ['dtapuska+blinkwatch@chromium.org',
@@ -2002,7 +2034,6 @@
     'blink_shadow_dom': ['hayato@chromium.org'],
     'blink_spellcheck' : ['timvolodine@chromium.org',
                           'xiaochengh+watch@chromium.org'],
-    'blink_spv2_layout_tests': ['pdr+virtualspv2watchlist@chromium.org'],
     'blink_streams': ['ricea+watch@chromium.org'],
     'blink_style': ['blink-reviews-style@chromium.org'],
     'blink_svg': ['dschulze@chromium.org',
@@ -2073,7 +2104,7 @@
                                  'martijn+crwatch@martijnc.be',
                                  'rsleevi+watch@chromium.org'],
     'chrome_cleaner': ['csharp+watch@chromium.org',
-                       'joenotcharles+watch@chromium.org'],
+                       'joenotcharles+watch@google.com'],
     'chrome_elf': ['caitkp+watch@chromium.org'],
     'chrome_grc': ['chrome-grc-reviews@chromium.org'],
     'chrome_views': ['tfarina@chromium.org'],
@@ -2116,6 +2147,7 @@
     'components_deps': ['blundell+watchlist@chromium.org',
                         'droger+watchlist@chromium.org',
                         'sdefresne+watchlist@chromium.org'],
+    'compositor_animator': ['mdjones+watch@chromium.org'],
     'content_bluetooth': ['mattreynolds+watch@chromium.org',
                           'ortuno+watch@chromium.org'],
     'content_loader': ['loading-reviews@chromium.org'],
@@ -2134,13 +2166,18 @@
            'tikuta+cc@chromium.org',
            'ukai+cc@chromium.org',
            'yyanagisawa+cc@chromium.org'],
-    'cr_elements': ['michaelpg+watch-elements@chromium.org',
+    'cr_elements': ['dbeam+watch-cr-elements@chromium.org',
+                    'michaelpg+watch-elements@chromium.org',
                     'stevenjb+watch-md-settings@chromium.org'],
     'cros_benchmarks': ['cros-perf-detectives@google.com',
                         'cywang@chromium.org',
                         'vovoy@chromium.org'],
     'crostini': ['crostini-ui@chromium.org'],
-    'custom_tabs': ['lizeb+watch-custom-tabs@chromium.org'],
+    'custom_tabs': ['amalova+watch@chromium.org',
+                    'lizeb+watch-custom-tabs@chromium.org',
+                    'peconn@chromium.org',
+                    'peter@chromium.org',
+                    'pshmakov@chromium.org'],
     'dbus': ['hashimoto+watch@chromium.org'],
     'deep_memory_profiler': ['dmikurube@chromium.org'],
     'device_bluetooth': ['mattreynolds+watch@chromium.org',
@@ -2154,7 +2191,8 @@
              'zhaobin+watch@chromium.org'],
     'disk_cache': ['gavinp+disk@chromium.org'],
     'download': ['dtrainor+watch@chromium.org'],
-    'downloads_ui': ['dtrainor+watch@chromium.org'],
+    'downloads_ui': ['dbeam+watch-downloads-ui@chromium.org',
+                     'dtrainor+watch@chromium.org'],
     'drive': ['tfarina@chromium.org'],
     'drive_resource_metadata': ['hashimoto+watch@chromium.org'],
     'eme': ['eme-reviews@chromium.org'],
@@ -2198,7 +2236,7 @@
                    'mcnee@chromium.org',
                    'wjmaclean@chromium.org'],
     'headless': ['headless-reviews@chromium.org'],
-    'history_ui': [],
+    'history_ui': ['dbeam+watch-history-ui@chromium.org'],
     'i18n': ['jshin+watch@chromium.org'],
     'importer': ['tfarina@chromium.org'],
     'incident_reporting': ['grt+watch@chromium.org'],
@@ -2219,10 +2257,10 @@
                 'ramyan+watch@chromium.org'],
     'ios': ['ios-reviews@chromium.org'],
     'ios_chrome': ['ios-reviews+chrome@chromium.org',
-                   'noyau+watch@chromium.org',
                    'marq+watch@chromium.org'],
     'ios_clean': ['ios-reviews+clean@chromium.org',
                   'marq+scrutinize@chromium.org'],
+    'ios_flags': ['noyau+watch@chromium.org'],
     'ios_showcase': ['ios-reviews+showcase@chromium.org',
                      'marq+watch@chromium.org'],
     'ios_web': ['ios-reviews+web@chromium.org',
@@ -2245,13 +2283,10 @@
     'linux_fonts': ['derat+watch@chromium.org'],
     'linux_sandboxing': ['jln+watch@chromium.org'],
     'linux_seccomp_bpf': ['jln+watch@chromium.org'],
-    'login': ['vabr+watchlistlogin@chromium.org'],
     'mac' : ['mac-reviews@chromium.org'],
     'manifest': ['mlamouri+watch-manifest@chromium.org'],
     'mash_buildbot_filters': ['dxie+watch@chromium.org',
                               'jamescook+watch@chromium.org'],
-    'md_settings': ['michaelpg+watch-md-settings@chromium.org',
-                    'stevenjb+watch-md-settings@chromium.org'],
     'media': ['feature-media-reviews@chromium.org'],
     'media_capture_from_element': ['emircan+watch+capturefromdom@chromium.org'],
     'media_controls': ['steimel+watch-mediacontrols@chromium.org'],
@@ -2273,7 +2308,6 @@
                      'pthatcher+watch@chromium.org',
                      'takumif+watch@chromium.org'],
     'media_win': ['media-win-reviews@chromium.org'],
-    'memory_coordinator': ['chrome-grc-reviews+memory@chromium.org'],
     'message_loop': ['sadrul@chromium.org'],
     'metrics': ['asvitkine+watch@chromium.org'],
     'metrics_xml_files': ['asvitkine+watch@chromium.org'],
@@ -2306,10 +2340,8 @@
     'nfc': ['mattreynolds+watch@chromium.org'],
     'notifications': ['peter@chromium.org'],
     'nqe': ['tbansal+watch-nqe@chromium.org'],
-    'ntp_snippets': ['ntp-dev+reviews@chromium.org',
-                     'noyau+watch@chromium.org'],
-    'ntp_tiles': ['ntp-dev+reviews@chromium.org',
-                  'noyau+watch@chromium.org'],
+    'ntp_snippets': ['ntp-dev+reviews@chromium.org'],
+    'ntp_tiles': ['ntp-dev+reviews@chromium.org'],
     'offline_items_collection': ['peter@chromium.org'],
     'offline_pages': ['chili+watch@chromium.org',
                       'carlosk+watch@chromium.org',
@@ -2319,8 +2351,7 @@
                       'petewil+watch@chromium.org',
                       'romax+watch@chromium.org'],
     'omnibox': ['jdonnelly+watch@chromium.org'],
-    'optimization_guide': ['dougarnett+watch-optguide@chromium.org',
-                           'sophiechang+watch-optguide@chromium.org'],
+    'optimization_guide': ['dougarnett+watch-optguide@chromium.org'],
     'origin_trials': ['chasej+watch@chromium.org',
                       'iclelland+watch@chromium.org'],
     'ozone': ['kalyan.kondapally@intel.com',
@@ -2340,7 +2371,6 @@
                'jennb@chromium.org',
                'jianli@chromium.org'],
     'password_manager': ['gcasto+watchlist@chromium.org',
-                         'vabr+watchlistpasswordmanager@chromium.org',
                          'vasilii+watchlistpasswordmanager@chromium.org'],
     'payments': ['rouslan+payments@chromium.org',
                  'gogerald+paymentswatch@chromium.org',
@@ -2361,7 +2391,8 @@
                     'timloh+watch@chromium.org'],
     'picture_in_picture': ['beaufort.francois+pip@gmail.com'],
     'policy_templates': ['ljusten+watch@chromium.org'],
-    'polymer': ['michaelpg+watch-polymer@chromium.org'],
+    'polymer': ['dbeam+watch-polymer@chromium.org',
+                'michaelpg+watch-polymer@chromium.org'],
     'popup_blocker': ['csharrison+watch-popups@chromium.org'],
     'precache': ['wifiprefetch-reviews@google.com'],
     'prepopulated_engines': ['vasilii+watch@chromium.org'],
@@ -2380,6 +2411,11 @@
                       'vakh+watch@chromium.org'],
     'screen_orientation': ['mlamouri+watch-screen-orientation@chromium.org'],
     'security': ['security-watchlist@chromium.org'],
+    'send_tab_to_self': ['hansberry+watch-send_tab_to_self@chromium.org',
+                         'tgupta+watch@chromium.org',
+                         'jeffreycohen+watch-send_tab_to_self@chromium.org',
+                         'jlklein+watch-send_tab_to_self@chromium.org',
+                         'jhawkins+watch-send_tab_to_self@chromium.org'],
     'service_worker': ['horo+watch@chromium.org',
                        'jsbell+serviceworker@chromium.org',
                        'kinuko+serviceworker@chromium.org',
@@ -2387,6 +2423,9 @@
                        'serviceworker-reviews@chromium.org',
                        'shimazu+serviceworker@chromium.org'],
     'services_public': ['blundell+services-watchlist@chromium.org'],
+    'settings': ['dbeam+watch-settings@chromium.org',
+                 'michaelpg+watch-md-settings@chromium.org',
+                 'stevenjb+watch-md-settings@chromium.org'],
     'settings_reset_prompt': ['alito+watch@chromium.org'],
     'site_engagement': ['dominickn+watch-engagement@chromium.org'],
     'site_instance': ['ajwong+watch@chromium.org',
@@ -2416,6 +2455,8 @@
                           'wnwen+watch@chromium.org'],
     'subresource_filter': ['subresource-filter-reviews@chromium.org'],
     'supervised_users': [],
+    'surface_layer_for_video': [ 'lethalantidote@chromium.org',
+                                 'liberato@chromium.org'],
     'sync': ['sync-reviews@chromium.org'],
     'syncfs': ['kinuko+fileapi@chromium.org',
                'nhiroki@chromium.org',
@@ -2455,7 +2496,8 @@
     'touch_selection': ['ajith.v@samsung.com',
                         'ajith.v@chromium.org'],
     'tracing': ['tracing+reviews@chromium.org',
-                'wfh+watch@chromium.org'],
+                'wfh+watch@chromium.org',
+                'spang+watch@chromium.org'],
     'ui_compositor': ['cc-bugs@chromium.org'],
     'ui_display_win': ['robliao+watch@chromium.org'],
     'ui_resources': ['oshima+watch@chromium.org'],
@@ -2473,7 +2515,9 @@
                          'dfaden+virtualkb@google.com',
                          'yhanada+watchvk@chromium.org'],
     'virtual_reality': ['feature-vr-reviews@chromium.org'],
+    'vulkan': ['cblume+vulkan@chromium.org'],
     'wake_lock': ['mattreynolds+watch@chromium.org'],
+    'web_dev_style': ['dbeam+watch-web-dev-style@chromium.org'],
     'web_package': ['twifkak+watch@chromium.org'],
     'web_share': ['mgiuca+watch@chromium.org'],
     'webauthn': ['webauthn-reviews@chromium.org'],
@@ -2484,10 +2528,12 @@
                          'markusheintz@chromium.org',
                          'msramek+watch@chromium.org',
                          'raymes+watch@chromium.org'],
+    'webui_backend': ['dbeam+watch-webui-backend@chromium.org'],
     'windows_sandboxing': ['wfh+watch@chromium.org'],
     'x11': ['derat+watch@chromium.org',
             'sadrul@chromium.org',
             'yusukes+watch@chromium.org'],
+    'zlib': ['cblume+zlib@chromium.org'],
     'zoom': ['wjmaclean@chromium.org'],
   },
 }
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index 5302d57..a467362e 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -3,12 +3,13 @@
 # found in the LICENSE file.
 
 import("//android_webview/system_webview_apk_tmpl.gni")
-import("//android_webview/webview_repack_locales.gni")
 import("//android_webview/variables.gni")
-import("//build/config/android/chrome_version.gni")
+import("//android_webview/webview_repack_locales.gni")
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 import("//build/config/locales.gni")
+import("//chrome/android/chrome_common_shared_library.gni")
+import("//chrome/android/chrome_public_apk_tmpl.gni")
 import("//chrome/android/trichrome.gni")
 import("//components/spellcheck/spellcheck_build_features.gni")
 import("//tools/grit/repack.gni")
@@ -47,6 +48,7 @@
     "java/src/org/chromium/android_webview/AwCookieManager.java",
     "java/src/org/chromium/android_webview/AwDebug.java",
     "java/src/org/chromium/android_webview/AwDevToolsServer.java",
+    "java/src/org/chromium/android_webview/AwDrawFnImpl.java",
     "java/src/org/chromium/android_webview/AwFeatureList.java",
     "java/src/org/chromium/android_webview/AwFormDatabase.java",
     "java/src/org/chromium/android_webview/AwGLFunctor.java",
@@ -55,11 +57,11 @@
     "java/src/org/chromium/android_webview/AwMetricsServiceClient.java",
     "java/src/org/chromium/android_webview/AwPdfExporter.java",
     "java/src/org/chromium/android_webview/AwPicture.java",
+    "java/src/org/chromium/android_webview/AwProxyController.java",
     "java/src/org/chromium/android_webview/AwQuotaManagerBridge.java",
     "java/src/org/chromium/android_webview/AwRenderProcess.java",
     "java/src/org/chromium/android_webview/AwResource.java",
     "java/src/org/chromium/android_webview/AwSettings.java",
-    "java/src/org/chromium/android_webview/AwTokenBindingManager.java",
     "java/src/org/chromium/android_webview/AwTracingController.java",
     "java/src/org/chromium/android_webview/AwVariationsSeedBridge.java",
     "java/src/org/chromium/android_webview/AwWebContentsDelegate.java",
@@ -425,27 +427,26 @@
       "//v8($android_secondary_abi_toolchain)",
     ]
   }
+}
 
-  shared_library("monochrome") {
-    deps = [
-      ":webview_entry_point",
-    ]
-    configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
-    configs += [ "//build/config/android:hide_all_but_jni" ]
-    if (use_lld) {
-      configs += [ "//build/config/android:lld_pack_relocations" ]
+if (current_abi_is_webview_only) {
+  template("webview_library") {
+    chrome_common_shared_library(target_name) {
+      forward_variables_from(invoker, "*")
+      deps = [
+        ":webview_entry_point",
+      ]
+      is_webview = true
     }
+  }
 
-    if (target_cpu != "mipsel" && target_cpu != "mips64el") {
-      # .gnu.hash support added in Android M. Without this flag, library will also
-      # contain an unused .hash section. (http://crbug.com/742525#c28)
-      # Not to be used for MIPS arhitecture since MIPS does not
-      # support hashstyle gnu: http://crbug.com/811306
-      ldflags = [ "-Wl,--hash-style=gnu" ]
-    }
+  # The webview-only library needs the same library name as the browser
+  # library, since the system webview factory will differentiate only by ABI.
+  webview_library("monochrome") {
+  }
 
-    public_configs = extra_chrome_shared_library_configs
-    deps += extra_chrome_shared_library_deps
+  # Bundle-specific webview library. Currently identical, but may diverge.
+  webview_library("monochrome_base") {
   }
 }
 
@@ -494,6 +495,8 @@
     "browser/aw_devtools_server.h",
     "browser/aw_download_manager_delegate.cc",
     "browser/aw_download_manager_delegate.h",
+    "browser/aw_draw_fn_impl.cc",
+    "browser/aw_draw_fn_impl.h",
     "browser/aw_feature_list.cc",
     "browser/aw_feature_list.h",
     "browser/aw_feature_list_creator.cc",
@@ -527,6 +530,7 @@
     "browser/aw_print_manager.h",
     "browser/aw_printing_message_filter.cc",
     "browser/aw_printing_message_filter.h",
+    "browser/aw_proxy_controller.cc",
     "browser/aw_proxying_url_loader_factory.cc",
     "browser/aw_proxying_url_loader_factory.h",
     "browser/aw_quota_manager_bridge.cc",
@@ -583,8 +587,6 @@
     "browser/deferred_gpu_command_service.h",
     "browser/find_helper.cc",
     "browser/find_helper.h",
-    "browser/gl_view_renderer_manager.cc",
-    "browser/gl_view_renderer_manager.h",
     "browser/hardware_renderer.cc",
     "browser/hardware_renderer.h",
     "browser/icon_helper.cc",
@@ -621,10 +623,10 @@
     "browser/net/init_native_callback.h",
     "browser/net/input_stream_reader.cc",
     "browser/net/input_stream_reader.h",
-    "browser/net/token_binding_manager.cc",
-    "browser/net/token_binding_manager.h",
     "browser/net_helpers.cc",
     "browser/net_helpers.h",
+    "browser/net_network_service/android_stream_reader_url_loader.cc",
+    "browser/net_network_service/android_stream_reader_url_loader.h",
     "browser/parent_compositor_draw_constraints.cc",
     "browser/parent_compositor_draw_constraints.h",
     "browser/parent_output_surface.cc",
@@ -645,7 +647,6 @@
     "browser/popup_touch_handle_drawable.h",
     "browser/render_thread_manager.cc",
     "browser/render_thread_manager.h",
-    "browser/render_thread_manager_client.h",
     "browser/renderer_host/auto_login_parser.cc",
     "browser/renderer_host/auto_login_parser.h",
     "browser/renderer_host/aw_render_view_host_ext.cc",
@@ -658,7 +659,6 @@
     "browser/state_serializer.h",
     "browser/surfaces_instance.cc",
     "browser/surfaces_instance.h",
-    "browser/token_binding_manager_bridge.cc",
     "browser/tracing/aw_trace_event_args_whitelist.cc",
     "browser/tracing/aw_trace_event_args_whitelist.h",
     "browser/tracing/aw_tracing_controller.cc",
@@ -697,6 +697,7 @@
     "lib/aw_main_delegate.h",
     "lib/webview_jni_onload.cc",
     "lib/webview_jni_onload.h",
+    "public/browser/draw_fn.h",
     "public/browser/draw_gl.h",
     "public/browser/draw_sw.h",
     "renderer/aw_content_renderer_client.cc",
@@ -735,8 +736,10 @@
     "//components/autofill/content/renderer",
     "//components/cdm/browser",
     "//components/cdm/renderer",
+    "//components/crash/android:crashpad_main",
     "//components/crash/content/app",
     "//components/crash/content/browser",
+    "//components/crash/core/common",
     "//components/download/public/common:public",
     "//components/embedder_support/android:web_contents_delegate",
     "//components/google/core/browser",
@@ -782,6 +785,7 @@
     "//content",
     "//content/public/app:both",
     "//content/public/browser",
+    "//content/public/common",
     "//content/public/common:content_descriptor_keys",
     "//content/public/common:service_names",
     "//crypto",
@@ -802,6 +806,7 @@
     "//storage/browser",
     "//storage/common",
     "//third_party/blink/public:blink",
+    "//third_party/crashpad/crashpad/client",
     "//ui/base",
     "//ui/events:gesture_detection",
     "//ui/gfx",
@@ -850,8 +855,10 @@
     "java/src/org/chromium/android_webview/AwCookieManager.java",
     "java/src/org/chromium/android_webview/AwDebug.java",
     "java/src/org/chromium/android_webview/AwDevToolsServer.java",
+    "java/src/org/chromium/android_webview/AwDrawFnImpl.java",
     "java/src/org/chromium/android_webview/AwFeatureList.java",
     "java/src/org/chromium/android_webview/AwFormDatabase.java",
+    "java/src/org/chromium/android_webview/AwFunctor.java",
     "java/src/org/chromium/android_webview/AwGeolocationPermissions.java",
     "java/src/org/chromium/android_webview/AwGLFunctor.java",
     "java/src/org/chromium/android_webview/AwHttpAuthHandler.java",
@@ -862,6 +869,7 @@
     "java/src/org/chromium/android_webview/AwPdfExporter.java",
     "java/src/org/chromium/android_webview/AwPicture.java",
     "java/src/org/chromium/android_webview/AwPrintDocumentAdapter.java",
+    "java/src/org/chromium/android_webview/AwProxyController.java",
     "java/src/org/chromium/android_webview/AwSafeBrowsingConfigHelper.java",
     "java/src/org/chromium/android_webview/AwSafeBrowsingResponse.java",
     "java/src/org/chromium/android_webview/AwQuotaManagerBridge.java",
@@ -876,7 +884,6 @@
     "java/src/org/chromium/android_webview/AwSettings.java",
     "java/src/org/chromium/android_webview/AwSupportLibIsomorphic.java",
     "java/src/org/chromium/android_webview/AwSwitches.java",
-    "java/src/org/chromium/android_webview/AwTokenBindingManager.java",
     "java/src/org/chromium/android_webview/AwTracingController.java",
     "java/src/org/chromium/android_webview/AwViewMethods.java",
     "java/src/org/chromium/android_webview/AwViewAndroidDelegate.java",
@@ -924,6 +931,7 @@
     "//components/autofill/android:autofill_java",
     "//components/autofill/android:provider_java",
     "//components/background_task_scheduler:background_task_scheduler_task_ids_java",
+    "//components/crash/android:handler_java",
     "//components/crash/android:java",
     "//components/embedder_support/android:web_contents_delegate_java",
     "//components/minidump_uploader:minidump_uploader_java",
@@ -964,7 +972,7 @@
     "//android_webview/proto:aw_variations_seed_proto_java",
     "//base:base_java",
     "//components/variations/android:variations_java",
-    "//third_party/protobuf:protobuf_lite_javalib",
+    "//third_party/android_deps:com_google_protobuf_protobuf_lite_java",
   ]
 }
 
@@ -1103,7 +1111,6 @@
 
 if (public_android_sdk) {
   system_webview_apk_tmpl("system_webview_apk") {
-    version_name = chrome_version_name
     android_manifest = system_webview_android_manifest
     android_manifest_dep = ":system_webview_manifest"
     deps = upstream_only_webview_deps
@@ -1111,7 +1118,6 @@
   }
 
   system_webview_apk_tmpl("trichrome_webview_apk") {
-    version_name = chrome_version_name
     android_manifest = trichrome_webview_android_manifest
     android_manifest_dep = ":trichrome_webview_manifest"
     deps = upstream_only_webview_deps
diff --git a/android_webview/OWNERS b/android_webview/OWNERS
index 84a80b2..9e9ad7c 100644
--- a/android_webview/OWNERS
+++ b/android_webview/OWNERS
@@ -4,5 +4,8 @@
 tobiasjs@chromium.org
 torne@chromium.org
 
+# Translation artifacts:
+per-file *.xtb=file://tools/translation/TRANSLATION_OWNERS
+
 # TEAM: android-webview-dev@chromium.org
 # COMPONENT: Mobile>WebView
diff --git a/android_webview/apk/java/proguard.flags b/android_webview/apk/java/proguard.flags
index 95fe04a..ff0cc8f 100644
--- a/android_webview/apk/java/proguard.flags
+++ b/android_webview/apk/java/proguard.flags
@@ -34,6 +34,11 @@
   public *;
 }
 
+# Functor classes with native methods implemented in Android.
+-keep class com.android.webview.chromium.DrawFunctor
+-keep class com.android.webview.chromium.DrawGLFunctor
+-keep class com.android.webview.chromium.GraphicsUtils
+
 # Linker dynamically casts to $TestRunner when running tests. We don't run these
 # tests in WebView.
 -dontnote org.chromium.base.library_loader.Linker$TestRunner
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS
index d400175..65957ae 100644
--- a/android_webview/browser/DEPS
+++ b/android_webview/browser/DEPS
@@ -11,10 +11,12 @@
   "+components/autofill/core/browser",
   "+components/autofill/core/common",
   "+components/cdm/browser",
+  "+components/crash/content/app",
   "+components/crash/content/browser",
   "+components/crash/core",
   "+components/download/public/common",
   "+components/heap_profiling",
+  "+components/minidump_uploader",
   "+components/navigation_interception",
   "+components/policy/core/browser",
   "+components/policy/core/common",
@@ -53,9 +55,17 @@
   "+services/network/public",
   "+services/service_manager/public/cpp",
 
+  # network service related unit tests
+  "+services/network/test",
+  "+mojo/core/embedder/embedder.h",
+  "+mojo/public/cpp/system",
+
   "+storage/browser/quota",
   "+storage/common/quota",
 
+  "+third_party/crashpad/crashpad/client",
+  "+third_party/crashpad/crashpad/util",
+
   "+ui/gfx",
   "+ui/gl",
   "+ui/touch_selection/touch_handle.h",
diff --git a/android_webview/browser/android_protocol_handler.cc b/android_webview/browser/android_protocol_handler.cc
index 08e8cda..25f6f79 100644
--- a/android_webview/browser/android_protocol_handler.cc
+++ b/android_webview/browser/android_protocol_handler.cc
@@ -233,16 +233,12 @@
 }
 
 static ScopedJavaLocalRef<jstring>
-JNI_AndroidProtocolHandler_GetAndroidAssetPath(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& /*clazz*/) {
+JNI_AndroidProtocolHandler_GetAndroidAssetPath(JNIEnv* env) {
   return ConvertUTF8ToJavaString(env, android_webview::kAndroidAssetPath);
 }
 
 static ScopedJavaLocalRef<jstring>
-JNI_AndroidProtocolHandler_GetAndroidResourcePath(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& /*clazz*/) {
+JNI_AndroidProtocolHandler_GetAndroidResourcePath(JNIEnv* env) {
   return ConvertUTF8ToJavaString(env, android_webview::kAndroidResourcePath);
 }
 
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc
index dd214e2..35941e4 100644
--- a/android_webview/browser/aw_autofill_client.cc
+++ b/android_webview/browser/aw_autofill_client.cc
@@ -35,22 +35,6 @@
 
 namespace android_webview {
 
-// Ownership: The native object is created (if autofill enabled) and owned by
-// AwContents. The native object creates the java peer which handles most
-// autofill functionality at the java side. The java peer is owned by Java
-// AwContents. The native object only maintains a weak ref to it.
-AwAutofillClient::AwAutofillClient(WebContents* contents)
-    : web_contents_(contents) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> delegate;
-  delegate.Reset(
-      Java_AwAutofillClient_create(env, reinterpret_cast<intptr_t>(this)));
-
-  AwContents* aw_contents = AwContents::FromWebContents(web_contents_);
-  aw_contents->SetAwAutofillClient(delegate);
-  java_ref_ = JavaObjectWeakGlobalRef(env, delegate);
-}
-
 AwAutofillClient::~AwAutofillClient() {
   HideAutofillPopup();
 }
@@ -63,6 +47,16 @@
   return save_form_data_;
 }
 
+autofill::PersonalDataManager* AwAutofillClient::GetPersonalDataManager() {
+  return nullptr;
+}
+
+autofill::AutocompleteHistoryManager*
+AwAutofillClient::GetAutocompleteHistoryManager() {
+  return AwContentBrowserClient::GetAwBrowserContext()
+      ->GetAutocompleteHistoryManager();
+}
+
 PrefService* AwAutofillClient::GetPrefs() {
   return user_prefs::UserPrefs::Get(
       AwContentBrowserClient::GetAwBrowserContext());
@@ -76,18 +70,22 @@
   return nullptr;
 }
 
-autofill::payments::PaymentsClient* AwAutofillClient::GetPaymentsClient() {
-  return nullptr;
-}
-
 autofill::FormDataImporter* AwAutofillClient::GetFormDataImporter() {
   return nullptr;
 }
 
+autofill::payments::PaymentsClient* AwAutofillClient::GetPaymentsClient() {
+  return nullptr;
+}
+
 autofill::LegacyStrikeDatabase* AwAutofillClient::GetLegacyStrikeDatabase() {
   return nullptr;
 }
 
+autofill::StrikeDatabase* AwAutofillClient::GetStrikeDatabase() {
+  return nullptr;
+}
+
 ukm::UkmRecorder* AwAutofillClient::GetUkmRecorder() {
   return nullptr;
 }
@@ -108,17 +106,83 @@
   return security_state::SecurityLevel::SECURITY_LEVEL_COUNT;
 }
 
-autofill::PersonalDataManager* AwAutofillClient::GetPersonalDataManager() {
-  return nullptr;
+void AwAutofillClient::ShowAutofillSettings(bool show_credit_card_settings) {
+  NOTIMPLEMENTED();
 }
 
-scoped_refptr<autofill::AutofillWebDataService>
-AwAutofillClient::GetDatabase() {
-  android_webview::AwFormDatabaseService* service =
-      static_cast<android_webview::AwBrowserContext*>(
-          web_contents_->GetBrowserContext())
-          ->GetFormDatabaseService();
-  return service->get_autofill_webdata_service();
+void AwAutofillClient::ShowUnmaskPrompt(
+    const autofill::CreditCard& card,
+    UnmaskCardReason reason,
+    base::WeakPtr<autofill::CardUnmaskDelegate> delegate) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::OnUnmaskVerificationResult(PaymentsRpcResult result) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::ShowLocalCardMigrationDialog(
+    base::OnceClosure show_migration_dialog_closure) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::ConfirmMigrateLocalCardToCloud(
+    std::unique_ptr<base::DictionaryValue> legal_message,
+    const std::vector<autofill::MigratableCreditCard>& migratable_credit_cards,
+    LocalCardMigrationCallback start_migrating_cards_callback) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::ShowLocalCardMigrationResults(
+    const bool has_server_error,
+    const base::string16& tip_message,
+    const std::vector<autofill::MigratableCreditCard>& migratable_credit_cards,
+    MigrationDeleteCardCallback delete_local_card_callback) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::ConfirmSaveAutofillProfile(
+    const autofill::AutofillProfile& profile,
+    base::OnceClosure callback) {
+  // Since there is no confirmation needed to save an Autofill Profile,
+  // running |callback| will proceed with saving |profile|.
+  std::move(callback).Run();
+}
+
+void AwAutofillClient::ConfirmSaveCreditCardLocally(
+    const autofill::CreditCard& card,
+    bool show_prompt,
+    LocalSaveCardPromptCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::ConfirmAccountNameFixFlow(
+    base::OnceCallback<void(const base::string16&)> callback) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::ConfirmSaveCreditCardToCloud(
+    const autofill::CreditCard& card,
+    std::unique_ptr<base::DictionaryValue> legal_message,
+    bool should_request_name_from_user,
+    bool should_request_expiration_date_from_user,
+    bool show_prompt,
+    UploadSaveCardPromptCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::ConfirmCreditCardFillAssist(
+    const autofill::CreditCard& card,
+    base::OnceClosure callback) {
+  NOTIMPLEMENTED();
+}
+
+bool AwAutofillClient::HasCreditCardScanFeature() {
+  return false;
+}
+
+void AwAutofillClient::ScanCreditCard(const CreditCardScanCallback& callback) {
+  NOTIMPLEMENTED();
 }
 
 void AwAutofillClient::ShowAutofillPopup(
@@ -140,6 +204,107 @@
                         suggestions);
 }
 
+void AwAutofillClient::UpdateAutofillPopupDataListValues(
+    const std::vector<base::string16>& values,
+    const std::vector<base::string16>& labels) {
+  // Leaving as an empty method since updating autofill popup window
+  // dynamically does not seem to be a useful feature for android webview.
+  // See crrev.com/18102002 if need to implement.
+}
+
+void AwAutofillClient::HideAutofillPopup() {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return;
+  delegate_.reset();
+  Java_AwAutofillClient_hideAutofillPopup(env, obj);
+}
+
+bool AwAutofillClient::IsAutocompleteEnabled() {
+  bool enabled = GetSaveFormData();
+  if (!autocomplete_uma_recorded_) {
+    UMA_HISTOGRAM_BOOLEAN("Autofill.AutocompleteEnabled", enabled);
+    autocomplete_uma_recorded_ = true;
+  }
+  return enabled;
+}
+
+void AwAutofillClient::PropagateAutofillPredictions(
+    content::RenderFrameHost* rfh,
+    const std::vector<autofill::FormStructure*>& forms) {}
+
+void AwAutofillClient::DidFillOrPreviewField(
+    const base::string16& autofilled_value,
+    const base::string16& profile_full_name) {}
+
+bool AwAutofillClient::IsContextSecure() {
+  content::SSLStatus ssl_status;
+  content::NavigationEntry* navigation_entry =
+      web_contents_->GetController().GetLastCommittedEntry();
+  if (!navigation_entry)
+    return false;
+
+  ssl_status = navigation_entry->GetSSL();
+  // Note: The implementation below is a copy of the one in
+  // ChromeAutofillClient::IsContextSecure, and should be kept in sync
+  // until crbug.com/505388 gets implemented.
+  return navigation_entry->GetURL().SchemeIsCryptographic() &&
+         ssl_status.certificate &&
+         (!net::IsCertStatusError(ssl_status.cert_status) ||
+          net::IsCertStatusMinorError(ssl_status.cert_status)) &&
+         !(ssl_status.content_status &
+           content::SSLStatus::RAN_INSECURE_CONTENT);
+}
+
+bool AwAutofillClient::ShouldShowSigninPromo() {
+  return false;
+}
+
+bool AwAutofillClient::AreServerCardsSupported() {
+  return true;
+}
+
+void AwAutofillClient::ExecuteCommand(int id) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::LoadRiskData(
+    base::OnceCallback<void(const std::string&)> callback) {
+  NOTIMPLEMENTED();
+}
+
+void AwAutofillClient::Dismissed(JNIEnv* env,
+                                 const JavaParamRef<jobject>& obj) {
+  anchor_view_.Reset();
+}
+
+void AwAutofillClient::SuggestionSelected(JNIEnv* env,
+                                          const JavaParamRef<jobject>& object,
+                                          jint position) {
+  if (delegate_) {
+    delegate_->DidAcceptSuggestion(suggestions_[position].value,
+                                   suggestions_[position].frontend_id,
+                                   position);
+  }
+}
+
+// Ownership: The native object is created (if autofill enabled) and owned by
+// AwContents. The native object creates the java peer which handles most
+// autofill functionality at the java side. The java peer is owned by Java
+// AwContents. The native object only maintains a weak ref to it.
+AwAutofillClient::AwAutofillClient(WebContents* contents)
+    : web_contents_(contents) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> delegate;
+  delegate.Reset(
+      Java_AwAutofillClient_create(env, reinterpret_cast<intptr_t>(this)));
+
+  AwContents* aw_contents = AwContents::FromWebContents(web_contents_);
+  aw_contents->SetAwAutofillClient(delegate);
+  java_ref_ = JavaObjectWeakGlobalRef(env, delegate);
+}
+
 void AwAutofillClient::ShowAutofillPopupImpl(
     const gfx::RectF& element_bounds,
     bool is_rtl,
@@ -179,169 +344,6 @@
   Java_AwAutofillClient_showAutofillPopup(env, obj, view, is_rtl, data_array);
 }
 
-void AwAutofillClient::UpdateAutofillPopupDataListValues(
-    const std::vector<base::string16>& values,
-    const std::vector<base::string16>& labels) {
-  // Leaving as an empty method since updating autofill popup window
-  // dynamically does not seem to be a useful feature for android webview.
-  // See crrev.com/18102002 if need to implement.
-}
-
-void AwAutofillClient::HideAutofillPopup() {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
-    return;
-  delegate_.reset();
-  Java_AwAutofillClient_hideAutofillPopup(env, obj);
-}
-
-bool AwAutofillClient::IsAutocompleteEnabled() {
-  bool enabled = GetSaveFormData();
-  if (!autocomplete_uma_recorded_) {
-    UMA_HISTOGRAM_BOOLEAN("Autofill.AutocompleteEnabled", enabled);
-    autocomplete_uma_recorded_ = true;
-  }
-  return enabled;
-}
-
-void AwAutofillClient::PropagateAutofillPredictions(
-    content::RenderFrameHost* rfh,
-    const std::vector<autofill::FormStructure*>& forms) {}
-
-void AwAutofillClient::DidFillOrPreviewField(
-    const base::string16& autofilled_value,
-    const base::string16& profile_full_name) {}
-
-void AwAutofillClient::DidInteractWithNonsecureCreditCardInput() {}
-
-bool AwAutofillClient::IsContextSecure() {
-  content::SSLStatus ssl_status;
-  content::NavigationEntry* navigation_entry =
-      web_contents_->GetController().GetLastCommittedEntry();
-  if (!navigation_entry)
-    return false;
-
-  ssl_status = navigation_entry->GetSSL();
-  // Note: The implementation below is a copy of the one in
-  // ChromeAutofillClient::IsContextSecure, and should be kept in sync
-  // until crbug.com/505388 gets implemented.
-  return navigation_entry->GetURL().SchemeIsCryptographic() &&
-         ssl_status.certificate &&
-         (!net::IsCertStatusError(ssl_status.cert_status) ||
-          net::IsCertStatusMinorError(ssl_status.cert_status)) &&
-         !(ssl_status.content_status &
-           content::SSLStatus::RAN_INSECURE_CONTENT);
-}
-
-bool AwAutofillClient::ShouldShowSigninPromo() {
-  return false;
-}
-
-void AwAutofillClient::ExecuteCommand(int id) {
-  NOTIMPLEMENTED();
-}
-
-bool AwAutofillClient::AreServerCardsSupported() {
-  return true;
-}
-
-void AwAutofillClient::Dismissed(JNIEnv* env,
-                                 const JavaParamRef<jobject>& obj) {
-  anchor_view_.Reset();
-}
-
-void AwAutofillClient::SuggestionSelected(JNIEnv* env,
-                                          const JavaParamRef<jobject>& object,
-                                          jint position) {
-  if (delegate_) {
-    delegate_->DidAcceptSuggestion(suggestions_[position].value,
-                                   suggestions_[position].frontend_id,
-                                   position);
-  }
-}
-
-void AwAutofillClient::ShowAutofillSettings(bool show_credit_card_settings) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ShowUnmaskPrompt(
-    const autofill::CreditCard& card,
-    UnmaskCardReason reason,
-    base::WeakPtr<autofill::CardUnmaskDelegate> delegate) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::OnUnmaskVerificationResult(PaymentsRpcResult result) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ShowLocalCardMigrationDialog(
-    base::OnceClosure show_migration_dialog_closure) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ConfirmAccountNameFixFlow(
-    base::OnceCallback<void(const base::string16&)> callback) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ConfirmMigrateLocalCardToCloud(
-    std::unique_ptr<base::DictionaryValue> legal_message,
-    const std::vector<autofill::MigratableCreditCard>& migratable_credit_cards,
-    LocalCardMigrationCallback start_migrating_cards_callback) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ConfirmSaveAutofillProfile(
-    const autofill::AutofillProfile& profile,
-    base::OnceClosure callback) {
-  // Since there is no confirmation needed to save an Autofill Profile,
-  // running |callback| will proceed with saving |profile|.
-  std::move(callback).Run();
-}
-
-void AwAutofillClient::ConfirmSaveCreditCardLocally(
-    const autofill::CreditCard& card,
-    bool show_prompt,
-    base::OnceClosure callback) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ConfirmSaveCreditCardToCloud(
-    const autofill::CreditCard& card,
-    std::unique_ptr<base::DictionaryValue> legal_message,
-    bool should_request_name_from_user,
-    bool should_request_expiration_date_from_user,
-    bool show_prompt,
-    UserAcceptedUploadCallback callback) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ShowLocalCardMigrationResults(
-    const base::string16& tip_message,
-    const std::vector<autofill::MigratableCreditCard>&
-        migratable_credit_cards) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::ConfirmCreditCardFillAssist(
-    const autofill::CreditCard& card,
-    base::OnceClosure callback) {
-  NOTIMPLEMENTED();
-}
-
-void AwAutofillClient::LoadRiskData(
-    base::OnceCallback<void(const std::string&)> callback) {
-  NOTIMPLEMENTED();
-}
-
-bool AwAutofillClient::HasCreditCardScanFeature() {
-  return false;
-}
-
-void AwAutofillClient::ScanCreditCard(const CreditCardScanCallback& callback) {
-  NOTIMPLEMENTED();
-}
+WEB_CONTENTS_USER_DATA_KEY_IMPL(AwAutofillClient)
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_autofill_client.h b/android_webview/browser/aw_autofill_client.h
index eca5533..18f2783 100644
--- a/android_webview/browser/aw_autofill_client.h
+++ b/android_webview/browser/aw_autofill_client.h
@@ -17,6 +17,7 @@
 #include "ui/android/view_android.h"
 
 namespace autofill {
+class AutocompleteHistoryManager;
 class AutofillPopupDelegate;
 class CardUnmaskDelegate;
 class CreditCard;
@@ -24,6 +25,7 @@
 class LegacyStrikeDatabase;
 class MigratableCreditCard;
 class PersonalDataManager;
+class StrikeDatabase;
 }
 
 namespace content {
@@ -60,13 +62,15 @@
 
   // AutofillClient:
   autofill::PersonalDataManager* GetPersonalDataManager() override;
-  scoped_refptr<autofill::AutofillWebDataService> GetDatabase() override;
+  autofill::AutocompleteHistoryManager* GetAutocompleteHistoryManager()
+      override;
   PrefService* GetPrefs() override;
   syncer::SyncService* GetSyncService() override;
   identity::IdentityManager* GetIdentityManager() override;
-  autofill::payments::PaymentsClient* GetPaymentsClient() override;
   autofill::FormDataImporter* GetFormDataImporter() override;
+  autofill::payments::PaymentsClient* GetPaymentsClient() override;
   autofill::LegacyStrikeDatabase* GetLegacyStrikeDatabase() override;
+  autofill::StrikeDatabase* GetStrikeDatabase() override;
   ukm::UkmRecorder* GetUkmRecorder() override;
   ukm::SourceId GetUkmSourceId() override;
   autofill::AddressNormalizer* GetAddressNormalizer() override;
@@ -79,33 +83,34 @@
   void OnUnmaskVerificationResult(PaymentsRpcResult result) override;
   void ShowLocalCardMigrationDialog(
       base::OnceClosure show_migration_dialog_closure) override;
-  void ConfirmAccountNameFixFlow(
-      base::OnceCallback<void(const base::string16&)> callback) override;
   void ConfirmMigrateLocalCardToCloud(
       std::unique_ptr<base::DictionaryValue> legal_message,
       const std::vector<autofill::MigratableCreditCard>&
           migratable_credit_cards,
       LocalCardMigrationCallback start_migrating_cards_callback) override;
   void ShowLocalCardMigrationResults(
+      const bool has_server_error,
       const base::string16& tip_message,
       const std::vector<autofill::MigratableCreditCard>&
-          migratable_credit_cards) override;
+          migratable_credit_cards,
+      MigrationDeleteCardCallback delete_local_card_callback) override;
   void ConfirmSaveAutofillProfile(const autofill::AutofillProfile& profile,
                                   base::OnceClosure callback) override;
-  void ConfirmSaveCreditCardLocally(const autofill::CreditCard& card,
-                                    bool show_prompt,
-                                    base::OnceClosure callback) override;
+  void ConfirmSaveCreditCardLocally(
+      const autofill::CreditCard& card,
+      bool show_prompt,
+      LocalSaveCardPromptCallback callback) override;
+  void ConfirmAccountNameFixFlow(
+      base::OnceCallback<void(const base::string16&)> callback) override;
   void ConfirmSaveCreditCardToCloud(
       const autofill::CreditCard& card,
       std::unique_ptr<base::DictionaryValue> legal_message,
       bool should_request_name_from_user,
       bool should_request_expiration_date_from_user,
       bool show_prompt,
-      UserAcceptedUploadCallback callback) override;
+      UploadSaveCardPromptCallback callback) override;
   void ConfirmCreditCardFillAssist(const autofill::CreditCard& card,
                                    base::OnceClosure callback) override;
-  void LoadRiskData(
-      base::OnceCallback<void(const std::string&)> callback) override;
   bool HasCreditCardScanFeature() override;
   void ScanCreditCard(const CreditCardScanCallback& callback) override;
   void ShowAutofillPopup(
@@ -124,12 +129,15 @@
       const std::vector<autofill::FormStructure*>& forms) override;
   void DidFillOrPreviewField(const base::string16& autofilled_value,
                              const base::string16& profile_full_name) override;
-  void DidInteractWithNonsecureCreditCardInput() override;
   bool IsContextSecure() override;
   bool ShouldShowSigninPromo() override;
   bool AreServerCardsSupported() override;
   void ExecuteCommand(int id) override;
 
+  // RiskDataLoader:
+  void LoadRiskData(
+      base::OnceCallback<void(const std::string&)> callback) override;
+
   void Dismissed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
   void SuggestionSelected(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj,
@@ -159,6 +167,8 @@
   // this client.
   bool autocomplete_uma_recorded_ = false;
 
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
   DISALLOW_COPY_AND_ASSIGN(AwAutofillClient);
 };
 
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index 3b247a9..7368ae9 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -22,6 +22,7 @@
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task/post_task.h"
+#include "components/autofill/core/browser/autocomplete_history_manager.h"
 #include "components/policy/core/browser/browser_policy_connector_base.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/triggers/trigger_manager.h"
@@ -209,6 +210,19 @@
   return url_request_context_getter_.get();
 }
 
+autofill::AutocompleteHistoryManager*
+AwBrowserContext::GetAutocompleteHistoryManager() {
+  if (!autocomplete_history_manager_) {
+    autocomplete_history_manager_ =
+        std::make_unique<autofill::AutocompleteHistoryManager>();
+    autocomplete_history_manager_->Init(
+        form_database_service_->get_autofill_webdata_service(),
+        user_pref_service_.get(), IsOffTheRecord());
+  }
+
+  return autocomplete_history_manager_.get();
+}
+
 base::FilePath AwBrowserContext::GetPath() const {
   return context_storage_path_;
 }
@@ -263,6 +277,11 @@
   return permission_manager_.get();
 }
 
+content::ClientHintsControllerDelegate*
+AwBrowserContext::GetClientHintsControllerDelegate() {
+  return nullptr;
+}
+
 content::BackgroundFetchDelegate*
 AwBrowserContext::GetBackgroundFetchDelegate() {
   // TODO(crbug.com/766077): Resolve whether to support or disable background
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index ab0346c..62d6a4a 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -23,6 +23,10 @@
 class GURL;
 class PrefService;
 
+namespace autofill {
+class AutocompleteHistoryManager;
+}
+
 namespace content {
 class PermissionControllerDelegate;
 class ResourceContext;
@@ -90,6 +94,7 @@
   AwQuotaManagerBridge* GetQuotaManagerBridge();
   AwFormDatabaseService* GetFormDatabaseService();
   AwURLRequestContextGetter* GetAwURLRequestContext();
+  autofill::AutocompleteHistoryManager* GetAutocompleteHistoryManager();
 
   web_restrictions::WebRestrictionsClient* GetWebRestrictionProvider();
 
@@ -104,6 +109,8 @@
   content::SSLHostStateDelegate* GetSSLHostStateDelegate() override;
   content::PermissionControllerDelegate* GetPermissionControllerDelegate()
       override;
+  content::ClientHintsControllerDelegate* GetClientHintsControllerDelegate()
+      override;
   content::BackgroundFetchDelegate* GetBackgroundFetchDelegate() override;
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
@@ -138,6 +145,8 @@
   scoped_refptr<AwURLRequestContextGetter> url_request_context_getter_;
   scoped_refptr<AwQuotaManagerBridge> quota_manager_bridge_;
   std::unique_ptr<AwFormDatabaseService> form_database_service_;
+  std::unique_ptr<autofill::AutocompleteHistoryManager>
+      autocomplete_history_manager_;
 
   std::unique_ptr<visitedlink::VisitedLinkMaster> visitedlink_master_;
   std::unique_ptr<content::ResourceContext> resource_context_;
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 42e713d..9db729b 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -30,7 +30,6 @@
 #include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "components/crash/content/browser/child_exit_observer_android.h"
-#include "components/crash/content/browser/crash_dump_manager_android.h"
 #include "components/heap_profiling/supervisor.h"
 #include "components/services/heap_profiling/public/cpp/settings.h"
 #include "components/user_prefs/user_prefs.h"
@@ -95,10 +94,9 @@
   }
 
   base::FilePath crash_dir;
-  if (crash_reporter::IsCrashReporterEnabled()) {
-    if (base::PathService::Get(android_webview::DIR_CRASH_DUMPS, &crash_dir)) {
-      if (!base::PathExists(crash_dir))
-        base::CreateDirectory(crash_dir);
+  if (base::PathService::Get(android_webview::DIR_CRASH_DUMPS, &crash_dir)) {
+    if (!base::PathExists(crash_dir)) {
+      base::CreateDirectory(crash_dir);
     }
   }
 
@@ -106,7 +104,7 @@
           switches::kWebViewSandboxedRenderer)) {
     // Create the renderers crash manager on the UI thread.
     ::crash_reporter::ChildExitObserver::GetInstance()->RegisterClient(
-        std::make_unique<AwBrowserTerminator>(crash_dir));
+        std::make_unique<AwBrowserTerminator>());
   }
 
   variations::InitCrashKeys();
diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc
index 8347981..ef87bc6 100644
--- a/android_webview/browser/aw_browser_terminator.cc
+++ b/android_webview/browser/aw_browser_terminator.cc
@@ -9,14 +9,11 @@
 
 #include "android_webview/browser/aw_render_process_gone_delegate.h"
 #include "android_webview/common/aw_descriptors.h"
-#include "android_webview/common/crash_reporter/aw_crash_reporter_client.h"
-#include "base/bind.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "base/sync_socket.h"
-#include "base/task/post_task.h"
-#include "components/crash/content/browser/crash_dump_manager_android.h"
-#include "content/public/browser/browser_task_traits.h"
+#include "base/strings/stringprintf.h"
+#include "components/crash/content/app/crashpad.h"
+#include "components/crash/content/browser/crash_metrics_reporter_android.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/child_process_launcher_utils.h"
@@ -36,13 +33,8 @@
 namespace {
 
 void GetAwRenderProcessGoneDelegatesForRenderProcess(
-    int render_process_id,
+    content::RenderProcessHost* rph,
     std::vector<AwRenderProcessGoneDelegate*>* delegates) {
-  content::RenderProcessHost* rph =
-      content::RenderProcessHost::FromID(render_process_id);
-  if (!rph)
-    return;
-
   std::unique_ptr<content::RenderWidgetHostIterator> widgets(
       content::RenderWidgetHost::GetRenderWidgetHosts());
   while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
@@ -59,28 +51,29 @@
   }
 }
 
-void OnRenderProcessGone(int process_host_id) {
+void OnRenderProcessGone(content::RenderProcessHost* host) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::vector<AwRenderProcessGoneDelegate*> delegates;
-  GetAwRenderProcessGoneDelegatesForRenderProcess(process_host_id, &delegates);
+  GetAwRenderProcessGoneDelegatesForRenderProcess(host, &delegates);
   for (auto* delegate : delegates)
-    delegate->OnRenderProcessGone(process_host_id);
+    delegate->OnRenderProcessGone(host->GetID());
 }
 
-void OnRenderProcessGoneDetail(int process_host_id,
-                               base::ProcessHandle child_process_pid,
+void OnRenderProcessGoneDetail(content::RenderProcessHost* host,
+                               base::ProcessId child_process_pid,
                                bool crashed) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::vector<AwRenderProcessGoneDelegate*> delegates;
-  GetAwRenderProcessGoneDelegatesForRenderProcess(process_host_id, &delegates);
+  GetAwRenderProcessGoneDelegatesForRenderProcess(host, &delegates);
   for (auto* delegate : delegates) {
     if (!delegate->OnRenderProcessGoneDetail(child_process_pid, crashed)) {
       if (crashed) {
-        crash_reporter::SuppressDumpGeneration();
         // Keeps this log unchanged, CTS test uses it to detect crash.
-        LOG(FATAL) << "Render process (" << child_process_pid << ")'s crash"
-                   << " wasn't handled by all associated  webviews, triggering"
-                   << " application crash.";
+        std::string message = base::StringPrintf(
+            "Render process (%d)'s crash wasn't handled by all associated  "
+            "webviews, triggering application crash.",
+            child_process_pid);
+        crash_reporter::CrashWithoutDumping(message);
       } else {
         // The render process was most likely killed for OOM or switching
         // WebView provider, to make WebView backward compatible, kills the
@@ -101,91 +94,26 @@
 
 }  // namespace
 
-AwBrowserTerminator::AwBrowserTerminator(base::FilePath crash_dump_dir)
-    : crash_dump_dir_(crash_dump_dir) {}
+AwBrowserTerminator::AwBrowserTerminator() = default;
 
-AwBrowserTerminator::~AwBrowserTerminator() {}
-
-void AwBrowserTerminator::OnChildStart(
-    int process_host_id,
-    content::PosixFileDescriptorInfo* mappings) {
-  DCHECK(content::CurrentlyOnProcessLauncherTaskRunner());
-
-  base::AutoLock auto_lock(process_host_id_to_pipe_lock_);
-  DCHECK(!ContainsKey(process_host_id_to_pipe_, process_host_id));
-
-  auto local_pipe = std::make_unique<base::SyncSocket>();
-  auto child_pipe = std::make_unique<base::SyncSocket>();
-  if (base::SyncSocket::CreatePair(local_pipe.get(), child_pipe.get())) {
-    process_host_id_to_pipe_[process_host_id] = std::move(local_pipe);
-    mappings->Transfer(kAndroidWebViewCrashSignalDescriptor,
-                       base::ScopedFD(dup(child_pipe->handle())));
-  }
-  if (crash_reporter::IsCrashReporterEnabled()) {
-    base::ScopedFD file(
-        breakpad::CrashDumpManager::GetInstance()->CreateMinidumpFileForChild(
-            process_host_id));
-    if (file != base::kInvalidPlatformFile)
-      mappings->Transfer(kAndroidMinidumpDescriptor, std::move(file));
-  }
-}
-
-void AwBrowserTerminator::OnChildExitAsync(
-    const ::crash_reporter::ChildExitObserver::TerminationInfo& info,
-    base::FilePath crash_dump_dir,
-    std::unique_ptr<base::SyncSocket> pipe) {
-  if (crash_reporter::IsCrashReporterEnabled()) {
-    breakpad::CrashDumpManager::GetInstance()->ProcessMinidumpFileFromChild(
-        crash_dump_dir, info);
-  }
-
-  if (!pipe.get() || info.normal_termination)
-    return;
-
-  bool crashed = false;
-
-  // If the child process hasn't written anything into the pipe. This implies
-  // that it was terminated via SIGKILL by the low memory killer.
-  if (pipe->Peek() >= sizeof(int)) {
-    int exit_code;
-    pipe->Receive(&exit_code, sizeof(exit_code));
-    LOG(ERROR) << "Renderer process (" << info.pid << ") crash detected (code "
-               << exit_code << ").";
-    crashed = true;
-  }
-
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&OnRenderProcessGoneDetail, info.process_host_id, info.pid,
-                     crashed));
-}
+AwBrowserTerminator::~AwBrowserTerminator() = default;
 
 void AwBrowserTerminator::OnChildExit(
-    const ::crash_reporter::ChildExitObserver::TerminationInfo& info) {
-  std::unique_ptr<base::SyncSocket> pipe;
+    const crash_reporter::ChildExitObserver::TerminationInfo& info) {
+  content::RenderProcessHost* rph =
+      content::RenderProcessHost::FromID(info.process_host_id);
+  OnRenderProcessGone(rph);
 
-  {
-    base::AutoLock auto_lock(process_host_id_to_pipe_lock_);
-    // We might get a NOTIFICATION_RENDERER_PROCESS_TERMINATED and a
-    // NOTIFICATION_RENDERER_PROCESS_CLOSED. In that case we only want
-    // to process the first notification.
-    const auto& iter = process_host_id_to_pipe_.find(info.process_host_id);
-    if (iter != process_host_id_to_pipe_.end()) {
-      pipe = std::move(iter->second);
-      DCHECK(pipe->handle() != base::SyncSocket::kInvalidHandle);
-      process_host_id_to_pipe_.erase(iter);
-    }
-  }
-  if (pipe.get()) {
-    OnRenderProcessGone(info.process_host_id);
+  crash_reporter::CrashMetricsReporter::GetInstance()->ChildProcessExited(info);
+
+  if (info.normal_termination) {
+    return;
   }
 
-  base::PostTaskWithTraits(
-      FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-      base::BindOnce(&AwBrowserTerminator::OnChildExitAsync, info,
-                     crash_dump_dir_, std::move(pipe)));
+  LOG(ERROR) << "Renderer process (" << info.pid << ") crash detected (code "
+             << info.crash_signo << ").";
+
+  OnRenderProcessGoneDetail(rph, info.pid, info.is_crashed());
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_browser_terminator.h b/android_webview/browser/aw_browser_terminator.h
index e3f7e9d..e75bf76 100644
--- a/android_webview/browser/aw_browser_terminator.h
+++ b/android_webview/browser/aw_browser_terminator.h
@@ -7,47 +7,24 @@
 
 #include <map>
 
-#include "base/synchronization/lock.h"
+#include "base/macros.h"
 #include "components/crash/content/browser/child_exit_observer_android.h"
 
-namespace base {
-class SyncSocket;
-}
-
 namespace android_webview {
 
-// This class manages behavior of the browser on renderer crashes when
-// microdumps are used for capturing the crash stack.  Normally, in this case
-// the browser doesn't need to do much, because a microdump is written into
-// Android log by the renderer process itself.  However, the browser may need to
-// crash itself on a renderer crash.  Since on Android renderers are not child
-// processes of the browser, it can't access the exit code. Instead, the browser
-// uses a dedicated pipe in order to receive the information about the renderer
-// crash status.
+// This class manages the browser's behavior in response to renderer exits. If
+// the application does not successfully handle a renderer crash/kill, the
+// browser needs to crash itself.
 class AwBrowserTerminator : public crash_reporter::ChildExitObserver::Client {
  public:
-  AwBrowserTerminator(base::FilePath crash_dump_dir);
+  AwBrowserTerminator();
   ~AwBrowserTerminator() override;
 
-  // crash_reporter::ChildExitObserver::Client implementation.
-  void OnChildStart(int process_host_id,
-                    content::PosixFileDescriptorInfo* mappings) override;
+  // crash_reporter::ChildExitObserver::Client
   void OnChildExit(
       const crash_reporter::ChildExitObserver::TerminationInfo& info) override;
 
  private:
-  static void OnChildExitAsync(
-      const crash_reporter::ChildExitObserver::TerminationInfo& info,
-      base::FilePath crash_dump_dir,
-      std::unique_ptr<base::SyncSocket> pipe);
-
-  base::FilePath crash_dump_dir_;
-
-  // This map should only be accessed with its lock aquired as it is accessed
-  // from the PROCESS_LAUNCHER, FILE, and UI threads.
-  base::Lock process_host_id_to_pipe_lock_;
-  std::map<int, std::unique_ptr<base::SyncSocket>> process_host_id_to_pipe_;
-
   DISALLOW_COPY_AND_ASSIGN(AwBrowserTerminator);
 };
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 84d2ce7..3d79a67f 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -25,12 +25,12 @@
 #include "android_webview/browser/aw_url_checker_delegate_impl.h"
 #include "android_webview/browser/aw_web_contents_view_delegate.h"
 #include "android_webview/browser/net/aw_url_request_context_getter.h"
+#include "android_webview/browser/net_helpers.h"
 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h"
 #include "android_webview/browser/tracing/aw_tracing_delegate.h"
 #include "android_webview/common/aw_content_client.h"
 #include "android_webview/common/aw_descriptors.h"
 #include "android_webview/common/aw_switches.h"
-#include "android_webview/common/crash_reporter/aw_crash_reporter_client.h"
 #include "android_webview/common/render_view_messages.h"
 #include "android_webview/common/url_constants.h"
 #include "android_webview/grit/aw_resources.h"
@@ -49,7 +49,7 @@
 #include "base/task/post_task.h"
 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
 #include "components/cdm/browser/cdm_message_filter_android.h"
-#include "components/crash/content/browser/child_exit_observer_android.h"
+#include "components/crash/content/browser/crash_handler_host_linux.h"
 #include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "components/policy/content/policy_blacklist_navigation_throttle.h"
 #include "components/policy/core/browser/browser_policy_connector_base.h"
@@ -72,10 +72,12 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_descriptors.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_loader_throttle.h"
+#include "content/public/common/user_agent.h"
 #include "content/public/common/web_preferences.h"
 #include "net/android/network_library.h"
 #include "net/log/net_log.h"
@@ -210,6 +212,21 @@
 
 }  // anonymous namespace
 
+std::string GetProduct() {
+  return version_info::GetProductNameAndVersionForUserAgent();
+}
+
+std::string GetUserAgent() {
+  // "Version/4.0" had been hardcoded in the legacy WebView.
+  std::string product = "Version/4.0 " + GetProduct();
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseMobileUserAgent)) {
+    product += " Mobile";
+  }
+  return content::BuildUserAgentFromProductAndExtraOSInfo(
+      product, "; wv", true /* include_android_build_number */);
+}
+
 // TODO(yirui): can use similar logic as in PrependToAcceptLanguagesIfNecessary
 // in chrome/browser/android/preferences/pref_service_bridge.cc
 // static
@@ -259,6 +276,20 @@
 
   network::mojom::NetworkContextPtr network_context;
   network::mojom::NetworkContextParamsPtr context_params =
+      GetNetworkContextParams();
+
+  content::GetNetworkService()->CreateNetworkContext(
+      MakeRequest(&network_context), std::move(context_params));
+
+  // Quic is not currently supported in WebView.
+  content::GetNetworkService()->DisableQuic();
+
+  return network_context;
+}
+
+network::mojom::NetworkContextParamsPtr
+AwContentBrowserClient::GetNetworkContextParams() {
+  network::mojom::NetworkContextParamsPtr context_params =
       network::mojom::NetworkContextParams::New();
   context_params->user_agent = GetUserAgent();
   // TODO(ntfschr): set this value to a proper value based on the user's
@@ -269,16 +300,24 @@
   context_params->enable_data_url_support = true;
 
   context_params->http_cache_enabled = true;
-  context_params->http_cache_max_size = 20 * 1024 * 1024;  // 20M
+  context_params->http_cache_max_size = GetHttpCacheSize();
   context_params->http_cache_path = AwBrowserContext::GetCacheDir();
 
-  content::GetNetworkService()->CreateNetworkContext(
-      MakeRequest(&network_context), std::move(context_params));
+  context_params->initial_ssl_config = network::mojom::SSLConfig::New();
+  // Allow SHA-1 to be used for locally-installed trust anchors, as WebView
+  // should behave like the Android system would.
+  context_params->initial_ssl_config->sha1_local_anchors_enabled = true;
+  // Do not enforce the Legacy Symantec PKI policies outlined in
+  // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html,
+  // defer to the Android system.
+  context_params->initial_ssl_config->symantec_enforcement_disabled = true;
 
-  // Quic is not currently supported in WebView.
-  content::GetNetworkService()->DisableQuic();
+  // WebView does not currently support Certificate Transparency.
+  context_params->enforce_chrome_ct_policy = false;
 
-  return network_context;
+  // WebView does not support ftp yet.
+  context_params->enable_ftp_url_support = false;
+  return context_params;
 }
 
 AwBrowserContext* AwContentBrowserClient::InitBrowserContext() {
@@ -368,7 +407,8 @@
            process_type == switches::kUtilityProcess)
         << process_type;
     // Pass crash reporter enabled state to renderer processes.
-    if (crash_reporter::IsCrashReporterEnabled()) {
+    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+            ::switches::kEnableCrashReporter)) {
       command_line->AppendSwitch(::switches::kEnableCrashReporter);
     }
   }
@@ -498,7 +538,7 @@
     content::RenderFrameHost* opener,
     const GURL& opener_url,
     const GURL& opener_top_level_frame_url,
-    const GURL& source_origin,
+    const url::Origin& source_origin,
     content::mojom::WindowContainerType container_type,
     const GURL& target_url,
     const content::Referrer& referrer,
@@ -588,8 +628,11 @@
   fd = ui::GetLocalePackFd(&region);
   mappings->ShareWithRegion(kAndroidWebViewLocalePakDescriptor, fd, region);
 
-  ::crash_reporter::ChildExitObserver::GetInstance()
-      ->BrowserChildProcessStarted(child_process_id, mappings);
+  int crash_signal_fd =
+      crashpad::CrashHandlerHost::Get()->GetDeathSignalSocket();
+  if (crash_signal_fd >= 0) {
+    mappings->Share(service_manager::kCrashDumpSignal, crash_signal_fd);
+  }
 }
 
 void AwContentBrowserClient::OverrideWebkitPrefs(
@@ -624,8 +667,8 @@
   return new AwDevToolsManagerDelegate();
 }
 
-std::unique_ptr<base::Value> AwContentBrowserClient::GetServiceManifestOverlay(
-    base::StringPiece name) {
+base::Optional<service_manager::Manifest>
+AwContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) {
   int id = -1;
   if (name == content::mojom::kBrowserServiceName)
     id = IDR_AW_BROWSER_MANIFEST_OVERLAY;
@@ -634,12 +677,13 @@
   else if (name == content::mojom::kUtilityServiceName)
     id = IDR_AW_UTILITY_MANIFEST_OVERLAY;
   if (id == -1)
-    return nullptr;
+    return base::nullopt;
 
   base::StringPiece manifest_contents =
       ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
           id, ui::ScaleFactor::SCALE_FACTOR_NONE);
-  return base::JSONReader::Read(manifest_contents);
+  return service_manager::Manifest::FromValueDeprecated(
+      base::JSONReader::Read(manifest_contents));
 }
 
 void AwContentBrowserClient::BindInterfaceRequestFromFrame(
@@ -871,6 +915,14 @@
   return true;
 }
 
+std::string AwContentBrowserClient::GetProduct() const {
+  return android_webview::GetProduct();
+}
+
+std::string AwContentBrowserClient::GetUserAgent() const {
+  return android_webview::GetUserAgent();
+}
+
 content::SpeechRecognitionManagerDelegate*
 AwContentBrowserClient::CreateSpeechRecognitionManagerDelegate() {
   return new AwSpeechRecognitionManagerDelegate();
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index d4e9371..5fa0fce 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -34,6 +34,9 @@
 class AwBrowserContext;
 class AwFeatureListCreator;
 
+std::string GetProduct();
+std::string GetUserAgent();
+
 class AwContentBrowserClient : public content::ContentBrowserClient {
  public:
   // This is what AwContentBrowserClient::GetAcceptLangs uses.
@@ -55,6 +58,7 @@
       content::BrowserContext* context,
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
+  network::mojom::NetworkContextParamsPtr GetNetworkContextParams();
 
   content::BrowserMainParts* CreateBrowserMainParts(
       const content::MainFunctionParams& parameters) override;
@@ -120,7 +124,7 @@
   bool CanCreateWindow(content::RenderFrameHost* opener,
                        const GURL& opener_url,
                        const GURL& opener_top_level_frame_url,
-                       const GURL& source_origin,
+                       const url::Origin& source_origin,
                        content::mojom::WindowContainerType container_type,
                        const GURL& target_url,
                        const content::Referrer& referrer,
@@ -153,7 +157,7 @@
   CreateThrottlesForNavigation(
       content::NavigationHandle* navigation_handle) override;
   content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override;
-  std::unique_ptr<base::Value> GetServiceManifestOverlay(
+  base::Optional<service_manager::Manifest> GetServiceManifestOverlay(
       base::StringPiece name) override;
   void BindInterfaceRequestFromFrame(
       content::RenderFrameHost* render_frame_host,
@@ -215,6 +219,8 @@
       network::mojom::URLLoaderFactoryRequest* factory_request,
       network::mojom::TrustedURLLoaderHeaderClientPtrInfo* header_client,
       bool* bypass_redirect_checks) override;
+  std::string GetProduct() const override;
+  std::string GetUserAgent() const override;
 
   AwFeatureListCreator* aw_feature_list_creator() {
     return aw_feature_list_creator_;
diff --git a/android_webview/browser/aw_content_browser_client_unittest.cc b/android_webview/browser/aw_content_browser_client_unittest.cc
index 462075e..e72a192 100644
--- a/android_webview/browser/aw_content_browser_client_unittest.cc
+++ b/android_webview/browser/aw_content_browser_client_unittest.cc
@@ -19,4 +19,33 @@
   EXPECT_FALSE(client.ShouldCreateTaskScheduler());
 }
 
+// Tests that constraints on trust for Symantec-issued certificates are not
+// enforced for the NetworkContext, as it should behave like the Android system.
+TEST_F(AwContentBrowserClientTest, SymantecPoliciesExempted) {
+  AwFeatureListCreator aw_feature_list_creator;
+  AwContentBrowserClient client(&aw_feature_list_creator);
+  network::mojom::NetworkContextParamsPtr network_context_params =
+      client.GetNetworkContextParams();
+
+  ASSERT_TRUE(network_context_params);
+  ASSERT_TRUE(network_context_params->initial_ssl_config);
+  ASSERT_TRUE(network_context_params->initial_ssl_config
+                  ->symantec_enforcement_disabled);
+}
+
+// Tests that SHA-1 is still allowed for locally-installed trust anchors,
+// including those in application manifests, as it should behave like
+// the Android system.
+TEST_F(AwContentBrowserClientTest, SHA1LocalAnchorsAllowed) {
+  AwFeatureListCreator aw_feature_list_creator;
+  AwContentBrowserClient client(&aw_feature_list_creator);
+  network::mojom::NetworkContextParamsPtr network_context_params =
+      client.GetNetworkContextParams();
+
+  ASSERT_TRUE(network_context_params);
+  ASSERT_TRUE(network_context_params->initial_ssl_config);
+  ASSERT_TRUE(
+      network_context_params->initial_ssl_config->sha1_local_anchors_enabled);
+}
+
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index 1b30da5..9ebecdc 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -112,6 +112,8 @@
 
 namespace android_webview {
 
+class CompositorFrameConsumer;
+
 namespace {
 
 bool g_should_download_favicons = false;
@@ -192,7 +194,6 @@
 // static
 void JNI_AwContents_UpdateDefaultLocale(
     JNIEnv* env,
-    const JavaParamRef<jclass>&,
     const JavaParamRef<jstring>& locale,
     const JavaParamRef<jstring>& locale_list) {
   *g_locale() = ConvertJavaStringToUTF8(env, locale);
@@ -238,8 +239,7 @@
       browser_view_renderer_(
           this,
           base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})),
-      web_contents_(std::move(web_contents)),
-      renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()) {
+      web_contents_(std::move(web_contents)) {
   base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1);
   icon_helper_.reset(new IconHelper(web_contents_.get()));
   icon_helper_->SetListener(this);
@@ -378,7 +378,7 @@
     base::MemoryPressureListener::NotifyMemoryPressure(
         base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
   }
-  SetAwGLFunctor(nullptr);
+  browser_view_renderer_.SetCurrentCompositorFrameConsumer(nullptr);
   AwContentsLifecycleNotifier::OnWebViewDestroyed();
 }
 
@@ -393,15 +393,12 @@
   return web_contents_->GetJavaWebContents();
 }
 
-void AwContents::SetAwGLFunctor(AwGLFunctor* functor) {
+void AwContents::SetCompositorFrameConsumer(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj,
+    jlong compositor_frame_consumer) {
   browser_view_renderer_.SetCurrentCompositorFrameConsumer(
-      functor ? functor->GetCompositorFrameConsumer() : nullptr);
-}
-
-void AwContents::SetAwGLFunctor(JNIEnv* env,
-                                const base::android::JavaParamRef<jobject>& obj,
-                                jlong gl_functor) {
-  SetAwGLFunctor(reinterpret_cast<AwGLFunctor*>(gl_functor));
+      reinterpret_cast<CompositorFrameConsumer*>(compositor_frame_consumer));
 }
 
 ScopedJavaLocalRef<jobject> AwContents::GetRenderProcess(
@@ -424,7 +421,6 @@
 }
 
 static jlong JNI_AwContents_Init(JNIEnv* env,
-                                 const JavaParamRef<jclass>&,
                                  const JavaParamRef<jobject>& browser_context) {
   // TODO(joth): Use |browser_context| to get the native BrowserContext, rather
   // than hard-code the default instance lookup here.
@@ -435,9 +431,7 @@
   return reinterpret_cast<intptr_t>(new AwContents(std::move(web_contents)));
 }
 
-static jboolean JNI_AwContents_HasRequiredHardwareExtensions(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&) {
+static jboolean JNI_AwContents_HasRequiredHardwareExtensions(JNIEnv* env) {
   ScopedAllowInitGLBindings scoped_allow_init_gl_bindings;
   // Make sure GPUInfo is collected. This will initialize GL bindings,
   // collect GPUInfo, and compute GpuFeatureInfo if they have not been
@@ -447,26 +441,22 @@
 }
 
 static void JNI_AwContents_SetAwDrawSWFunctionTable(JNIEnv* env,
-                                                    const JavaParamRef<jclass>&,
                                                     jlong function_table) {
   RasterHelperSetAwDrawSWFunctionTable(
       reinterpret_cast<AwDrawSWFunctionTable*>(function_table));
 }
 
 static void JNI_AwContents_SetAwDrawGLFunctionTable(JNIEnv* env,
-                                                    const JavaParamRef<jclass>&,
                                                     jlong function_table) {}
 
 // static
-jint JNI_AwContents_GetNativeInstanceCount(JNIEnv* env,
-                                           const JavaParamRef<jclass>&) {
+jint JNI_AwContents_GetNativeInstanceCount(JNIEnv* env) {
   return base::subtle::NoBarrier_Load(&g_instance_count);
 }
 
 // static
 ScopedJavaLocalRef<jstring> JNI_AwContents_GetSafeBrowsingLocaleForTesting(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&) {
+    JNIEnv* env) {
   ScopedJavaLocalRef<jstring> locale =
       ConvertUTF8ToJavaString(env, base::i18n::GetConfiguredLocale());
   return locale;
@@ -1037,7 +1027,7 @@
   }
 
   // TODO(hush): Right now webview size is passed in as the auxiliary bitmap
-  // size, which might hurt performace (only for software draws with auxiliary
+  // size, which might hurt performance (only for software draws with auxiliary
   // bitmap). For better performance, get global visible rect, transform it
   // from screen space to view space, then intersect with the webview in
   // viewspace.  Use the resulting rect as the auxiliary bitmap.
@@ -1357,9 +1347,7 @@
   return reinterpret_cast<jlong>(autofill_provider_.get());
 }
 
-void JNI_AwContents_SetShouldDownloadFavicons(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& jclazz) {
+void JNI_AwContents_SetShouldDownloadFavicons(JNIEnv* env) {
   g_should_download_favicons = true;
 }
 
diff --git a/android_webview/browser/aw_contents.h b/android_webview/browser/aw_contents.h
index c623fc5..1570655 100644
--- a/android_webview/browser/aw_contents.h
+++ b/android_webview/browser/aw_contents.h
@@ -16,7 +16,6 @@
 #include "android_webview/browser/browser_view_renderer.h"
 #include "android_webview/browser/browser_view_renderer_client.h"
 #include "android_webview/browser/find_helper.h"
-#include "android_webview/browser/gl_view_renderer_manager.h"
 #include "android_webview/browser/icon_helper.h"
 #include "android_webview/browser/permission/permission_request_handler_client.h"
 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
@@ -39,7 +38,6 @@
 namespace android_webview {
 
 class AwContentsClientBridge;
-class AwGLFunctor;
 class AwPdfExporter;
 class AwWebContentsDelegate;
 class PermissionRequestHandler;
@@ -103,9 +101,10 @@
   base::android::ScopedJavaLocalRef<jobject> GetWebContents(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
-  void SetAwGLFunctor(JNIEnv* env,
-                      const base::android::JavaParamRef<jobject>& obj,
-                      jlong gl_functor);
+  void SetCompositorFrameConsumer(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jlong compositor_frame_consumer);
 
   base::android::ScopedJavaLocalRef<jobject> GetRenderProcess(
       JNIEnv* env,
@@ -374,8 +373,6 @@
 
   void SetDipScaleInternal(float dip_scale);
 
-  void SetAwGLFunctor(AwGLFunctor* functor);
-
   JavaObjectWeakGlobalRef java_ref_;
   BrowserViewRenderer browser_view_renderer_;  // Must outlive |web_contents_|.
   std::unique_ptr<content::WebContents> web_contents_;
@@ -396,8 +393,6 @@
   // The first element in the list is always the currently pending request.
   std::list<OriginCallback> pending_geolocation_prompts_;
 
-  GLViewRendererManager::Key renderer_manager_key_;
-
   DISALLOW_COPY_AND_ASSIGN(AwContents);
 };
 
diff --git a/android_webview/browser/aw_contents_statics.cc b/android_webview/browser/aw_contents_statics.cc
index 47952182..e00917f 100644
--- a/android_webview/browser/aw_contents_statics.cc
+++ b/android_webview/browser/aw_contents_statics.cc
@@ -10,7 +10,6 @@
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
-#include "base/bind.h"
 #include "base/callback.h"
 #include "base/task/post_task.h"
 #include "components/google/core/common/google_util.h"
@@ -53,21 +52,11 @@
   Java_AwContentsStatics_safeBrowsingWhitelistAssigned(env, callback, success);
 }
 
-void ProxyOverrideChanged(const JavaRef<jobject>& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (callback.is_null())
-    return;
-  JNIEnv* env = AttachCurrentThread();
-  Java_AwContentsStatics_proxyOverrideChanged(env, callback);
-}
-
 }  // namespace
 
 // static
 ScopedJavaLocalRef<jstring>
-JNI_AwContentsStatics_GetSafeBrowsingPrivacyPolicyUrl(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&) {
+JNI_AwContentsStatics_GetSafeBrowsingPrivacyPolicyUrl(JNIEnv* env) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   GURL privacy_policy_url(
       security_interstitials::kSafeBrowsingPrivacyPolicyUrl);
@@ -81,7 +70,6 @@
 // static
 void JNI_AwContentsStatics_ClearClientCertPreferences(
     JNIEnv* env,
-    const JavaParamRef<jclass>&,
     const JavaParamRef<jobject>& callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   base::PostTaskWithTraitsAndReply(
@@ -93,16 +81,14 @@
 
 // static
 ScopedJavaLocalRef<jstring> JNI_AwContentsStatics_GetUnreachableWebDataUrl(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&) {
+    JNIEnv* env) {
   return base::android::ConvertUTF8ToJavaString(
       env, content::kUnreachableWebDataURL);
 }
 
 // static
 ScopedJavaLocalRef<jstring> JNI_AwContentsStatics_GetProductVersion(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&) {
+    JNIEnv* env) {
   return base::android::ConvertUTF8ToJavaString(
       env, version_info::GetVersionNumber());
 }
@@ -110,7 +96,6 @@
 // static
 void JNI_AwContentsStatics_SetSafeBrowsingWhitelist(
     JNIEnv* env,
-    const JavaParamRef<jclass>&,
     const JavaParamRef<jobjectArray>& jrules,
     const JavaParamRef<jobject>& callback) {
   std::vector<std::string> rules;
@@ -126,7 +111,6 @@
 // static
 void JNI_AwContentsStatics_SetServiceWorkerIoThreadClient(
     JNIEnv* env,
-    const JavaParamRef<jclass>&,
     const base::android::JavaParamRef<jobject>& io_thread_client,
     const base::android::JavaParamRef<jobject>& browser_context) {
   AwContentsIoThreadClient::SetServiceWorkerIoThreadClient(io_thread_client,
@@ -136,38 +120,8 @@
 // static
 void JNI_AwContentsStatics_SetCheckClearTextPermitted(
     JNIEnv* env,
-    const JavaParamRef<jclass>&,
     jboolean permitted) {
   AwURLRequestContextGetter::set_check_cleartext_permitted(permitted);
 }
 
-// static
-void JNI_AwContentsStatics_SetProxyOverride(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&,
-    const base::android::JavaParamRef<jstring>& jhost,
-    jint port,
-    const base::android::JavaParamRef<jobjectArray>& jexclusion_list,
-    const JavaParamRef<jobject>& callback) {
-  std::string host;
-  base::android::ConvertJavaStringToUTF8(env, jhost, &host);
-  std::vector<std::string> exclusion_list;
-  base::android::AppendJavaStringArrayToStringVector(env, jexclusion_list,
-                                                     &exclusion_list);
-  AwBrowserContext::GetDefault()->GetAwURLRequestContext()->SetProxyOverride(
-      host, port, exclusion_list,
-      base::BindOnce(&ProxyOverrideChanged,
-                     ScopedJavaGlobalRef<jobject>(env, callback)));
-}
-
-// static
-void JNI_AwContentsStatics_ClearProxyOverride(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&,
-    const JavaParamRef<jobject>& callback) {
-  AwBrowserContext::GetDefault()->GetAwURLRequestContext()->ClearProxyOverride(
-      base::BindOnce(&ProxyOverrideChanged,
-                     ScopedJavaGlobalRef<jobject>(env, callback)));
-}
-
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_debug.cc b/android_webview/browser/aw_debug.cc
index 7b3abaf..0ebdd8a 100644
--- a/android_webview/browser/aw_debug.cc
+++ b/android_webview/browser/aw_debug.cc
@@ -2,16 +2,29 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "android_webview/common/aw_channel.h"
 #include "android_webview/common/crash_reporter/aw_crash_reporter_client.h"
 #include "android_webview/common/crash_reporter/crash_keys.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
+#include "base/android/path_utils.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/threading/thread_restrictions.h"
+#include "components/crash/content/app/crash_reporter_client.h"
+#include "components/crash/content/app/crashpad.h"
 #include "components/crash/core/common/crash_key.h"
+#include "components/minidump_uploader/rewrite_minidumps_as_mimes.h"
+#include "components/version_info/version_info.h"
+#include "components/version_info/version_info_values.h"
 #include "jni/AwDebug_jni.h"
+#include "third_party/crashpad/crashpad/client/crash_report_database.h"
+#include "third_party/crashpad/crashpad/util/net/http_body.h"
+#include "third_party/crashpad/crashpad/util/net/http_multipart_builder.h"
+
+#include <memory>
 
 using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertUTF8ToJavaString;
@@ -20,9 +33,100 @@
 
 namespace android_webview {
 
+namespace {
+
+class AwDebugCrashReporterClient
+    : public ::crash_reporter::CrashReporterClient {
+ public:
+  AwDebugCrashReporterClient() = default;
+  ~AwDebugCrashReporterClient() override = default;
+
+  void GetProductNameAndVersion(std::string* product_name,
+                                std::string* version,
+                                std::string* channel) override {
+    *product_name = "AndroidWebView";
+    *version = PRODUCT_VERSION;
+    *channel =
+        version_info::GetChannelString(android_webview::GetChannelOrStable());
+  }
+
+  bool GetCrashDumpLocation(base::FilePath* debug_dir) override {
+    base::FilePath cache_dir;
+    if (!base::android::GetCacheDirectory(&cache_dir)) {
+      return false;
+    }
+    *debug_dir = cache_dir.Append(FILE_PATH_LITERAL("WebView")).Append("Debug");
+    return true;
+  }
+
+  void GetSanitizationInformation(const char* const** annotations_whitelist,
+                                  void** target_module,
+                                  bool* sanitize_stacks) override {
+    *annotations_whitelist = crash_keys::kWebViewCrashKeyWhiteList;
+    *target_module = nullptr;
+    *sanitize_stacks = true;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(AwDebugCrashReporterClient);
+};
+
+// Writes the most recent report in the database as a MIME to fd. Finishes by
+// deleting all reports from the database. Returns `true` if a report was
+// successfully found and written the file descriptor.
+bool WriteLastReportToFd(crashpad::CrashReportDatabase* db, int fd) {
+  std::vector<crashpad::CrashReportDatabase::Report> reports;
+  if (db->GetPendingReports(&reports) !=
+          crashpad::CrashReportDatabase::kNoError ||
+      !reports.size()) {
+    LOG(ERROR) << "no reports";
+    return false;
+  }
+
+  size_t most_recent_index = 0;
+  time_t most_recent_time = reports[0].creation_time;
+  for (size_t index = 1; index < reports.size(); ++index) {
+    if (reports[index].creation_time > most_recent_time) {
+      most_recent_index = index;
+      most_recent_time = reports[index].creation_time;
+    }
+  }
+
+  {
+    std::unique_ptr<const crashpad::CrashReportDatabase::UploadReport>
+        upload_report;
+    if (db->GetReportForUploading(reports[most_recent_index].uuid,
+                                  &upload_report,
+                                  /* report_metrics= */ false) !=
+        crashpad::CrashReportDatabase::kNoError) {
+      return false;
+    }
+
+    crashpad::HTTPMultipartBuilder builder;
+    pid_t pid;
+    if (!minidump_uploader::MimeifyReport(*upload_report.get(), &builder,
+                                          &pid)) {
+      return false;
+    }
+
+    crashpad::WeakFileHandleFileWriter writer(fd);
+    if (!minidump_uploader::WriteBodyToFile(builder.GetBodyStream().get(),
+                                            &writer)) {
+      return false;
+    }
+  }
+
+  for (size_t index = 0; index < reports.size(); ++index) {
+    db->DeleteReport(reports[index].uuid);
+  }
+  db->CleanDatabase(0);
+
+  return true;
+}
+
+}  // namespace
+
 static jboolean JNI_AwDebug_DumpWithoutCrashing(
     JNIEnv* env,
-    const JavaParamRef<jclass>& clazz,
     const JavaParamRef<jstring>& dump_path) {
   // This may be called from any thread, and we might be in a state
   // where it is impossible to post tasks, so we have to be prepared
@@ -33,27 +137,41 @@
                         base::File::FLAG_WRITE);
   if (!target.IsValid())
     return false;
-  // breakpad_linux::HandleCrashDump will close this fd once it is done.
-  return crash_reporter::DumpWithoutCrashingToFd(target.TakePlatformFile());
+
+  AwDebugCrashReporterClient client;
+  base::FilePath database_path;
+  if (!client.GetCrashDumpLocation(&database_path)) {
+    return false;
+  }
+
+  if (!base::CreateDirectory(database_path)) {
+    return false;
+  }
+
+  std::unique_ptr<crashpad::CrashReportDatabase> database =
+      crashpad::CrashReportDatabase::Initialize(database_path);
+  if (!database) {
+    return false;
+  }
+
+  if (!::crash_reporter::DumpWithoutCrashingForClient(&client)) {
+    return false;
+  }
+
+  return WriteLastReportToFd(database.get(), target.GetPlatformFile());
 }
 
-static void JNI_AwDebug_InitCrashKeysForWebViewTesting(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& clazz) {
+static void JNI_AwDebug_InitCrashKeysForWebViewTesting(JNIEnv* env) {
   crash_keys::InitCrashKeysForWebViewTesting();
 }
 
-static void JNI_AwDebug_SetWhiteListedKeyForTesting(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& clazz) {
+static void JNI_AwDebug_SetWhiteListedKeyForTesting(JNIEnv* env) {
   static ::crash_reporter::CrashKeyString<32> crash_key(
       "AW_WHITELISTED_DEBUG_KEY");
   crash_key.Set("AW_DEBUG_VALUE");
 }
 
-static void JNI_AwDebug_SetNonWhiteListedKeyForTesting(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& clazz) {
+static void JNI_AwDebug_SetNonWhiteListedKeyForTesting(JNIEnv* env) {
   static ::crash_reporter::CrashKeyString<32> crash_key(
       "AW_NONWHITELISTED_DEBUG_KEY");
   crash_key.Set("AW_DEBUG_VALUE");
diff --git a/android_webview/browser/aw_draw_fn_impl.cc b/android_webview/browser/aw_draw_fn_impl.cc
new file mode 100644
index 0000000..9bcfac48
--- /dev/null
+++ b/android_webview/browser/aw_draw_fn_impl.cc
@@ -0,0 +1,148 @@
+// 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 "android_webview/browser/aw_draw_fn_impl.h"
+
+#include "android_webview/public/browser/draw_gl.h"
+#include "base/stl_util.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "jni/AwDrawFnImpl_jni.h"
+
+using base::android::JavaParamRef;
+using content::BrowserThread;
+
+namespace android_webview {
+
+namespace {
+
+AwDrawFnFunctionTable* g_draw_fn_function_table = nullptr;
+
+void OnSyncWrapper(int functor, void* data, AwDrawFn_OnSyncParams* params) {
+  CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
+  static_cast<AwDrawFnImpl*>(data)->OnSync(params);
+}
+
+void OnContextDestroyedWrapper(int functor, void* data) {
+  CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
+  static_cast<AwDrawFnImpl*>(data)->OnContextDestroyed();
+}
+
+void OnDestroyedWrapper(int functor, void* data) {
+  CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
+  delete static_cast<AwDrawFnImpl*>(data);
+}
+
+void DrawGLWrapper(int functor, void* data, AwDrawFn_DrawGLParams* params) {
+  CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
+  static_cast<AwDrawFnImpl*>(data)->DrawGL(params);
+}
+
+void InitVkWrapper(int functor, void* data, AwDrawFn_InitVkParams* params) {
+  CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
+  static_cast<AwDrawFnImpl*>(data)->InitVk(params);
+}
+
+void DrawVkWrapper(int functor, void* data, AwDrawFn_DrawVkParams* params) {
+  CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
+  static_cast<AwDrawFnImpl*>(data)->DrawVk(params);
+}
+
+void PostDrawVkWrapper(int functor,
+                       void* data,
+                       AwDrawFn_PostDrawVkParams* params) {
+  CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
+  static_cast<AwDrawFnImpl*>(data)->PostDrawVk(params);
+}
+
+}  // namespace
+
+static void JNI_AwDrawFnImpl_SetDrawFnFunctionTable(JNIEnv* env,
+                                                    jlong function_table) {
+  g_draw_fn_function_table =
+      reinterpret_cast<AwDrawFnFunctionTable*>(function_table);
+}
+
+AwDrawFnImpl::AwDrawFnImpl()
+    : render_thread_manager_(
+          base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(g_draw_fn_function_table);
+
+  static AwDrawFnFunctorCallbacks g_functor_callbacks{
+      &OnSyncWrapper,      &OnContextDestroyedWrapper,
+      &OnDestroyedWrapper, &DrawGLWrapper,
+      &InitVkWrapper,      &DrawVkWrapper,
+      &PostDrawVkWrapper,
+  };
+
+  functor_handle_ =
+      g_draw_fn_function_table->create_functor(this, &g_functor_callbacks);
+}
+
+AwDrawFnImpl::~AwDrawFnImpl() {}
+
+void AwDrawFnImpl::ReleaseHandle(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  render_thread_manager_.RemoveFromCompositorFrameProducerOnUI();
+  g_draw_fn_function_table->release_functor(functor_handle_);
+}
+
+jint AwDrawFnImpl::GetFunctorHandle(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  return functor_handle_;
+}
+
+jlong AwDrawFnImpl::GetCompositorFrameConsumer(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  return reinterpret_cast<intptr_t>(GetCompositorFrameConsumer());
+}
+
+static jlong JNI_AwDrawFnImpl_Create(JNIEnv* env) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  return reinterpret_cast<intptr_t>(new AwDrawFnImpl());
+}
+
+void AwDrawFnImpl::OnSync(AwDrawFn_OnSyncParams* params) {
+  render_thread_manager_.CommitFrameOnRT();
+}
+
+void AwDrawFnImpl::OnContextDestroyed() {
+  RenderThreadManager::InsideHardwareReleaseReset release_reset(
+      &render_thread_manager_);
+  render_thread_manager_.DestroyHardwareRendererOnRT(false /* save_restore */);
+}
+
+void AwDrawFnImpl::DrawGL(AwDrawFn_DrawGLParams* params) {
+  struct HardwareRendererDrawParams hr_params {};
+  hr_params.clip_left = params->clip_left;
+  hr_params.clip_top = params->clip_top;
+  hr_params.clip_right = params->clip_right;
+  hr_params.clip_bottom = params->clip_bottom;
+  hr_params.width = params->width;
+  hr_params.height = params->height;
+  hr_params.is_layer = params->is_layer;
+
+  static_assert(base::size(decltype(params->transform){}) ==
+                    base::size(hr_params.transform),
+                "transform size mismatch");
+  for (size_t i = 0; i < base::size(hr_params.transform); ++i) {
+    hr_params.transform[i] = params->transform[i];
+  }
+  render_thread_manager_.DrawOnRT(false /* save_restore */, &hr_params);
+}
+
+void AwDrawFnImpl::InitVk(AwDrawFn_InitVkParams* params) {}
+
+void AwDrawFnImpl::DrawVk(AwDrawFn_DrawVkParams* params) {}
+
+void AwDrawFnImpl::PostDrawVk(AwDrawFn_PostDrawVkParams* params) {}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/aw_draw_fn_impl.h b/android_webview/browser/aw_draw_fn_impl.h
new file mode 100644
index 0000000..c854c00
--- /dev/null
+++ b/android_webview/browser/aw_draw_fn_impl.h
@@ -0,0 +1,47 @@
+// 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 ANDROID_WEBVIEW_BROWSER_AW_DRAW_FN_IMPL_H_
+#define ANDROID_WEBVIEW_BROWSER_AW_DRAW_FN_IMPL_H_
+
+#include "android_webview/browser/compositor_frame_consumer.h"
+#include "android_webview/browser/render_thread_manager.h"
+#include "android_webview/public/browser/draw_fn.h"
+#include "base/android/jni_weak_ref.h"
+
+namespace android_webview {
+
+class AwDrawFnImpl {
+ public:
+  AwDrawFnImpl();
+  ~AwDrawFnImpl();
+
+  void ReleaseHandle(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj);
+  jint GetFunctorHandle(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj);
+  jlong GetCompositorFrameConsumer(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+
+  int functor_handle() { return functor_handle_; }
+  void OnSync(AwDrawFn_OnSyncParams* params);
+  void OnContextDestroyed();
+  void DrawGL(AwDrawFn_DrawGLParams* params);
+  void InitVk(AwDrawFn_InitVkParams* params);
+  void DrawVk(AwDrawFn_DrawVkParams* params);
+  void PostDrawVk(AwDrawFn_PostDrawVkParams* params);
+
+ private:
+  CompositorFrameConsumer* GetCompositorFrameConsumer() {
+    return &render_thread_manager_;
+  }
+
+  int functor_handle_;
+  RenderThreadManager render_thread_manager_;
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_AW_DRAW_FN_IMPL_H_
diff --git a/android_webview/browser/aw_feature_list.cc b/android_webview/browser/aw_feature_list.cc
index 982e8ab..0ad91ce 100644
--- a/android_webview/browser/aw_feature_list.cc
+++ b/android_webview/browser/aw_feature_list.cc
@@ -55,13 +55,12 @@
 
 // Whether the application package name is logged in UMA.
 const base::Feature kWebViewUmaLogAppPackageName{
-    "WebViewUmaLogAppPackageName", base::FEATURE_DISABLED_BY_DEFAULT};
+    "WebViewUmaLogAppPackageName", base::FEATURE_ENABLED_BY_DEFAULT};
 
 }  // namespace features
 
 static jboolean JNI_AwFeatureList_IsEnabled(
     JNIEnv* env,
-    const JavaParamRef<jclass>& clazz,
     const JavaParamRef<jstring>& jfeature_name) {
   const base::Feature* feature =
       FindFeatureExposedToJava(ConvertJavaStringToUTF8(env, jfeature_name));
diff --git a/android_webview/browser/aw_feature_list_creator.cc b/android_webview/browser/aw_feature_list_creator.cc
index f479a0e..cf71dbd 100644
--- a/android_webview/browser/aw_feature_list_creator.cc
+++ b/android_webview/browser/aw_feature_list_creator.cc
@@ -47,10 +47,11 @@
 // These prefs go in the JsonPrefStore, and will persist across runs. Other
 // prefs go in the InMemoryPrefStore, and will be lost when the process ends.
 const char* const kPersistentPrefsWhitelist[] = {
-    // Random seed value for variation's entropy providers, used to assign
+    // Random seed values for variation's entropy providers, used to assign
     // experiment groups.
     metrics::prefs::kMetricsLowEntropySource,
     // Used by CachingPermutedEntropyProvider to cache generated values.
+    // TODO(crbug/912368): Remove this.
     variations::prefs::kVariationsPermutedEntropyCache,
 };
 
@@ -156,18 +157,21 @@
 
   // Populate FieldTrialList. Since low_entropy_provider is null, it will fall
   // back to the provider we previously gave to FieldTrialList, which is a low
-  // entropy provider. We only want one low entropy provider, because multiple
-  // CachingPermutedEntropyProvider objects would all try to cache their values
-  // in the same pref store, overwriting each other's.
+  // entropy provider.
   variations_field_trial_creator_->SetupFieldTrials(
       cc::switches::kEnableGpuBenchmarking, switches::kEnableFeatures,
       switches::kDisableFeatures, unforceable_field_trials,
       std::vector<std::string>(), /*low_entropy_provider=*/nullptr,
       std::make_unique<base::FeatureList>(), aw_field_trials_.get(),
       &ignored_safe_seed_manager);
+
+  // Activate a study which exercises permanent-consistency, to test the launch
+  // of permanent-consistency support in WebView.
+  // TODO(crbug/917537): Remove this after m73.
+  base::FieldTrialList::FindFullName("AndroidWebViewConsistencyTest");
 }
 
-void AwFeatureListCreator::CreateFetureListAndFieldTrials() {
+void AwFeatureListCreator::CreateFeatureListAndFieldTrials() {
   browser_policy_connector_ = std::make_unique<AwBrowserPolicyConnector>();
   local_state_ = CreatePrefService(browser_policy_connector_.get());
   AwMetricsServiceClient::GetInstance()->Initialize(local_state_.get());
diff --git a/android_webview/browser/aw_feature_list_creator.h b/android_webview/browser/aw_feature_list_creator.h
index d0768ef..79c0e4a 100644
--- a/android_webview/browser/aw_feature_list_creator.h
+++ b/android_webview/browser/aw_feature_list_creator.h
@@ -27,7 +27,7 @@
 
   // Initializes all necessary parameters to create the feature list and setup
   // field trials.
-  void CreateFetureListAndFieldTrials();
+  void CreateFeatureListAndFieldTrials();
 
   // Passes ownership of the |local_state_| to the caller.
   std::unique_ptr<PrefService> TakePrefService() {
diff --git a/android_webview/browser/aw_form_database.cc b/android_webview/browser/aw_form_database.cc
index 8da2a07..4c1a675 100644
--- a/android_webview/browser/aw_form_database.cc
+++ b/android_webview/browser/aw_form_database.cc
@@ -25,12 +25,12 @@
 }  // anonymous namespace
 
 // static
-jboolean JNI_AwFormDatabase_HasFormData(JNIEnv*, const JavaParamRef<jclass>&) {
+jboolean JNI_AwFormDatabase_HasFormData(JNIEnv*) {
   return GetFormDatabaseService()->HasFormData();
 }
 
 // static
-void JNI_AwFormDatabase_ClearFormData(JNIEnv*, const JavaParamRef<jclass>&) {
+void JNI_AwFormDatabase_ClearFormData(JNIEnv*) {
   GetFormDatabaseService()->ClearFormData();
 }
 
diff --git a/android_webview/browser/aw_form_database_service.cc b/android_webview/browser/aw_form_database_service.cc
index bf5fb76c..488bfb3 100644
--- a/android_webview/browser/aw_form_database_service.cc
+++ b/android_webview/browser/aw_form_database_service.cc
@@ -84,7 +84,7 @@
           base::IgnoreResult(&awds::GetCountOfValuesContainedBetween),
           autofill_data_, base::Time(), base::Time::Max(), this));
   {
-    base::ThreadRestrictions::ScopedAllowWait wait;
+    base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
     has_form_data_completion_.Wait();
   }
   return has_form_data_result_;
diff --git a/android_webview/browser/aw_gl_functor.cc b/android_webview/browser/aw_gl_functor.cc
index ac39690..ecc2b68 100644
--- a/android_webview/browser/aw_gl_functor.cc
+++ b/android_webview/browser/aw_gl_functor.cc
@@ -5,6 +5,7 @@
 #include "android_webview/browser/aw_gl_functor.h"
 
 #include "android_webview/public/browser/draw_gl.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -22,7 +23,7 @@
                            void* spare) {
   // |view_context| is the value that was returned from the java
   // AwContents.onPrepareDrawGL; this cast must match the code there.
-  reinterpret_cast<android_webview::RenderThreadManager*>(view_context)
+  reinterpret_cast<android_webview::AwGLFunctor*>(view_context)
       ->DrawGL(draw_info);
 }
 }
@@ -36,7 +37,6 @@
 AwGLFunctor::AwGLFunctor(const JavaObjectWeakGlobalRef& java_ref)
     : java_ref_(java_ref),
       render_thread_manager_(
-          this,
           base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ++g_instance_count;
@@ -75,31 +75,79 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  render_thread_manager_.DeleteHardwareRendererOnUI();
+  RenderThreadManager::InsideHardwareReleaseReset release_reset(
+      &render_thread_manager_);
+  DetachFunctorFromView();
+
+  // Receiving at least one frame is a precondition for
+  // initialization (such as looing up GL bindings and constructing
+  // hardware_renderer_).
+  bool draw_functor_succeeded = RequestInvokeGL(true);
+  if (!draw_functor_succeeded) {
+    LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?";
+    // Calling release on wrong thread intentionally.
+    render_thread_manager_.DestroyHardwareRendererOnRT(true /* save_restore */);
+  }
 }
 
-jlong AwGLFunctor::GetAwDrawGLViewContext(
+void AwGLFunctor::DrawGL(AwDrawGLInfo* draw_info) {
+  TRACE_EVENT0("android_webview,toplevel", "DrawFunctor");
+  bool save_restore = draw_info->version < 3;
+  switch (draw_info->mode) {
+    case AwDrawGLInfo::kModeSync:
+      TRACE_EVENT_INSTANT0("android_webview", "kModeSync",
+                           TRACE_EVENT_SCOPE_THREAD);
+      render_thread_manager_.CommitFrameOnRT();
+      break;
+    case AwDrawGLInfo::kModeProcessNoContext:
+      LOG(ERROR) << "Received unexpected kModeProcessNoContext";
+      FALLTHROUGH;
+    case AwDrawGLInfo::kModeProcess:
+      render_thread_manager_.DestroyHardwareRendererOnRT(save_restore);
+      break;
+    case AwDrawGLInfo::kModeDraw: {
+      HardwareRendererDrawParams params{
+          draw_info->clip_left,   draw_info->clip_top, draw_info->clip_right,
+          draw_info->clip_bottom, draw_info->width,    draw_info->height,
+          draw_info->is_layer,
+      };
+      static_assert(base::size(decltype(draw_info->transform){}) ==
+                        base::size(params.transform),
+                    "transform size mismatch");
+      for (unsigned int i = 0; i < base::size(params.transform); ++i) {
+        params.transform[i] = draw_info->transform[i];
+      }
+      render_thread_manager_.DrawOnRT(save_restore, &params);
+      break;
+    }
+  }
+}
+
+void AwGLFunctor::RemoveFromCompositorFrameProducer(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  return reinterpret_cast<intptr_t>(&render_thread_manager_);
+  render_thread_manager_.RemoveFromCompositorFrameProducerOnUI();
 }
 
-static jint JNI_AwGLFunctor_GetNativeInstanceCount(
+jlong AwGLFunctor::GetCompositorFrameConsumer(
     JNIEnv* env,
-    const JavaParamRef<jclass>&) {
+    const base::android::JavaParamRef<jobject>& obj) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  return reinterpret_cast<intptr_t>(GetCompositorFrameConsumer());
+}
+
+static jint JNI_AwGLFunctor_GetNativeInstanceCount(JNIEnv* env) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return g_instance_count;
 }
 
-static jlong JNI_AwGLFunctor_GetAwDrawGLFunction(JNIEnv* env,
-                                                 const JavaParamRef<jclass>&) {
+static jlong JNI_AwGLFunctor_GetAwDrawGLFunction(JNIEnv* env) {
   return reinterpret_cast<intptr_t>(&DrawGLFunction);
 }
 
 static jlong JNI_AwGLFunctor_Create(
     JNIEnv* env,
-    const JavaParamRef<jclass>&,
     const base::android::JavaParamRef<jobject>& obj) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return reinterpret_cast<intptr_t>(
diff --git a/android_webview/browser/aw_gl_functor.h b/android_webview/browser/aw_gl_functor.h
index 699474b..b54d513 100644
--- a/android_webview/browser/aw_gl_functor.h
+++ b/android_webview/browser/aw_gl_functor.h
@@ -7,32 +7,38 @@
 
 #include "android_webview/browser/compositor_frame_consumer.h"
 #include "android_webview/browser/render_thread_manager.h"
-#include "android_webview/browser/render_thread_manager_client.h"
 #include "base/android/jni_weak_ref.h"
 
+struct AwDrawGLInfo;
+
 namespace android_webview {
 
-class AwGLFunctor : public RenderThreadManagerClient {
+class AwGLFunctor {
  public:
-  bool RequestInvokeGL(bool wait_for_completion) override;
-  void DetachFunctorFromView() override;
-
   AwGLFunctor(const JavaObjectWeakGlobalRef& java_ref);
-  ~AwGLFunctor() override;
+  ~AwGLFunctor();
 
   void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
   void DeleteHardwareRenderer(JNIEnv* env,
                               const base::android::JavaParamRef<jobject>& obj);
-  jlong GetAwDrawGLViewContext(JNIEnv* env,
-                               const base::android::JavaParamRef<jobject>& obj);
+  void RemoveFromCompositorFrameProducer(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jlong GetCompositorFrameConsumer(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
   jlong GetAwDrawGLFunction(JNIEnv* env,
                             const base::android::JavaParamRef<jobject>& obj);
 
+  void DrawGL(AwDrawGLInfo* draw_info);
+
+ private:
+  bool RequestInvokeGL(bool wait_for_completion);
+  void DetachFunctorFromView();
   CompositorFrameConsumer* GetCompositorFrameConsumer() {
     return &render_thread_manager_;
   }
 
- private:
   JavaObjectWeakGlobalRef java_ref_;
   RenderThreadManager render_thread_manager_;
 };
diff --git a/android_webview/browser/aw_metrics_service_client.cc b/android_webview/browser/aw_metrics_service_client.cc
index 8f02742..53193d8 100644
--- a/android_webview/browser/aw_metrics_service_client.cc
+++ b/android_webview/browser/aw_metrics_service_client.cc
@@ -294,7 +294,6 @@
 // static
 void JNI_AwMetricsServiceClient_SetHaveMetricsConsent(
     JNIEnv* env,
-    const base::android::JavaParamRef<jclass>& jcaller,
     jboolean consent) {
   g_lazy_instance_.Pointer()->SetHaveMetricsConsent(consent);
 }
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
index 3a101d3..0ecad5b 100644
--- a/android_webview/browser/aw_permission_manager.cc
+++ b/android_webview/browser/aw_permission_manager.cc
@@ -6,11 +6,11 @@
 
 #include <memory>
 #include <string>
+#include <unordered_map>
 #include <utility>
 
 #include "android_webview/browser/aw_browser_permission_request_delegate.h"
 #include "base/callback.h"
-#include "base/containers/hash_tables.h"
 #include "base/logging.h"
 #include "content/public/browser/permission_controller.h"
 #include "content/public/browser/permission_type.h"
@@ -142,7 +142,7 @@
     return requesting + "," + embedding;
   }
 
-  using StatusMap = base::hash_map<std::string, PermissionStatus>;
+  using StatusMap = std::unordered_map<std::string, PermissionStatus>;
   StatusMap pmi_result_cache_;
 
   DISALLOW_COPY_AND_ASSIGN(LastRequestResultCache);
diff --git a/android_webview/browser/aw_print_manager.cc b/android_webview/browser/aw_print_manager.cc
index 221f47471..8dd231e 100644
--- a/android_webview/browser/aw_print_manager.cc
+++ b/android_webview/browser/aw_print_manager.cc
@@ -101,4 +101,6 @@
   render_frame_host->Send(reply_msg);
 }
 
+WEB_CONTENTS_USER_DATA_KEY_IMPL(AwPrintManager)
+
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_print_manager.h b/android_webview/browser/aw_print_manager.h
index f59c671..1734e4d 100644
--- a/android_webview/browser/aw_print_manager.h
+++ b/android_webview/browser/aw_print_manager.h
@@ -51,6 +51,8 @@
 
   printing::PrintSettings settings_;
 
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
   DISALLOW_COPY_AND_ASSIGN(AwPrintManager);
 };
 
diff --git a/android_webview/browser/aw_proxy_controller.cc b/android_webview/browser/aw_proxy_controller.cc
new file mode 100644
index 0000000..add6746
--- /dev/null
+++ b/android_webview/browser/aw_proxy_controller.cc
@@ -0,0 +1,96 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/aw_browser_context.h"
+#include "android_webview/browser/net/aw_url_request_context_getter.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/message_loop/message_loop_current.h"
+#include "content/public/browser/browser_thread.h"
+#include "jni/AwProxyController_jni.h"
+#include "net/proxy_resolution/proxy_config_service_android.h"
+
+using base::android::AttachCurrentThread;
+using base::android::HasException;
+using base::android::JavaParamRef;
+using base::android::JavaRef;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using content::BrowserThread;
+
+namespace android_webview {
+
+namespace {
+
+void ProxyOverrideChanged(const JavaRef<jobject>& obj,
+                          const JavaRef<jobject>& listener,
+                          const JavaRef<jobject>& executor) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (listener.is_null())
+    return;
+  JNIEnv* env = AttachCurrentThread();
+  Java_AwProxyController_proxyOverrideChanged(env, obj, listener, executor);
+  if (HasException(env)) {
+    // Tell the chromium message loop to not perform any tasks after the current
+    // one - we want to make sure we return to Java cleanly without first making
+    // any new JNI calls.
+    base::MessageLoopCurrentForUI::Get()->Abort();
+  }
+}
+
+}  // namespace
+
+ScopedJavaLocalRef<jstring> JNI_AwProxyController_SetProxyOverride(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const base::android::JavaParamRef<jobjectArray>& jurl_schemes,
+    const base::android::JavaParamRef<jobjectArray>& jproxy_urls,
+    const base::android::JavaParamRef<jobjectArray>& jbypass_rules,
+    const JavaParamRef<jobject>& listener,
+    const JavaParamRef<jobject>& executor) {
+  std::vector<std::string> url_schemes;
+  base::android::AppendJavaStringArrayToStringVector(env, jurl_schemes,
+                                                     &url_schemes);
+  std::vector<std::string> proxy_urls;
+  base::android::AppendJavaStringArrayToStringVector(env, jproxy_urls,
+                                                     &proxy_urls);
+  std::vector<net::ProxyConfigServiceAndroid::ProxyOverrideRule> proxy_rules;
+  int size = url_schemes.size();
+  DCHECK(url_schemes.size() == proxy_urls.size());
+  proxy_rules.reserve(size);
+  for (int i = 0; i < size; i++) {
+    proxy_rules.emplace_back(url_schemes[i], proxy_urls[i]);
+  }
+  std::vector<std::string> bypass_rules;
+  base::android::AppendJavaStringArrayToStringVector(env, jbypass_rules,
+                                                     &bypass_rules);
+
+  std::string result =
+      AwBrowserContext::GetDefault()
+          ->GetAwURLRequestContext()
+          ->SetProxyOverride(
+              proxy_rules, bypass_rules,
+              base::BindOnce(&ProxyOverrideChanged,
+                             ScopedJavaGlobalRef<jobject>(env, obj),
+                             ScopedJavaGlobalRef<jobject>(env, listener),
+                             ScopedJavaGlobalRef<jobject>(env, executor)));
+  return base::android::ConvertUTF8ToJavaString(env, result);
+}
+
+void JNI_AwProxyController_ClearProxyOverride(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& listener,
+    const JavaParamRef<jobject>& executor) {
+  AwBrowserContext::GetDefault()->GetAwURLRequestContext()->ClearProxyOverride(
+      base::BindOnce(&ProxyOverrideChanged,
+                     ScopedJavaGlobalRef<jobject>(env, obj),
+                     ScopedJavaGlobalRef<jobject>(env, listener),
+                     ScopedJavaGlobalRef<jobject>(env, executor)));
+}
+
+}  // namespace android_webview
\ No newline at end of file
diff --git a/android_webview/browser/aw_proxying_url_loader_factory.cc b/android_webview/browser/aw_proxying_url_loader_factory.cc
index bb1506b4..4639d4a 100644
--- a/android_webview/browser/aw_proxying_url_loader_factory.cc
+++ b/android_webview/browser/aw_proxying_url_loader_factory.cc
@@ -61,11 +61,9 @@
   void OnComplete(const network::URLLoaderCompletionStatus& status) override;
 
   // network::mojom::URLLoader
-  void FollowRedirect(
-      const base::Optional<std::vector<std::string>>&
-          to_be_removed_request_headers,
-      const base::Optional<net::HttpRequestHeaders>& modified_request_headers,
-      const base::Optional<GURL>& new_url) override;
+  void FollowRedirect(const std::vector<std::string>& removed_headers,
+                      const net::HttpRequestHeaders& modified_headers,
+                      const base::Optional<GURL>& new_url) override;
   void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
@@ -318,14 +316,11 @@
 // URLLoader methods.
 
 void InterceptedRequest::FollowRedirect(
-    const base::Optional<std::vector<std::string>>&
-        to_be_removed_request_headers,
-    const base::Optional<net::HttpRequestHeaders>& modified_request_headers,
+    const std::vector<std::string>& removed_headers,
+    const net::HttpRequestHeaders& modified_headers,
     const base::Optional<GURL>& new_url) {
-  if (target_loader_) {
-    target_loader_->FollowRedirect(to_be_removed_request_headers,
-                                   modified_request_headers, new_url);
-  }
+  if (target_loader_)
+    target_loader_->FollowRedirect(removed_headers, modified_headers, new_url);
 
   Restart();
 }
diff --git a/android_webview/browser/aw_quota_manager_bridge.cc b/android_webview/browser/aw_quota_manager_bridge.cc
index bd55933..a43ab3d 100644
--- a/android_webview/browser/aw_quota_manager_bridge.cc
+++ b/android_webview/browser/aw_quota_manager_bridge.cc
@@ -153,8 +153,7 @@
 
 // static
 jlong JNI_AwQuotaManagerBridge_GetDefaultNativeAwQuotaManagerBridge(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& clazz) {
+    JNIEnv* env) {
   AwBrowserContext* browser_context =
       AwContentBrowserClient::GetAwBrowserContext();
 
diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc
index f971a6c..95e06d5 100644
--- a/android_webview/browser/aw_render_thread_context_provider.cc
+++ b/android_webview/browser/aw_render_thread_context_provider.cc
@@ -28,13 +28,13 @@
 scoped_refptr<AwRenderThreadContextProvider>
 AwRenderThreadContextProvider::Create(
     scoped_refptr<gl::GLSurface> surface,
-    gpu::CommandBufferTaskExecutor* task_executor) {
-  return new AwRenderThreadContextProvider(surface, task_executor);
+    scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor) {
+  return new AwRenderThreadContextProvider(surface, std::move(task_executor));
 }
 
 AwRenderThreadContextProvider::AwRenderThreadContextProvider(
     scoped_refptr<gl::GLSurface> surface,
-    gpu::CommandBufferTaskExecutor* task_executor) {
+    scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor) {
   DCHECK(main_thread_checker_.CalledOnValidThread());
 
   // This is an onscreen context, wrapping the GLSurface given to us from
@@ -66,9 +66,9 @@
   limits.min_transfer_buffer_size = 64 * 1024;
 
   context_ = std::make_unique<gpu::GLInProcessContext>();
-  context_->Initialize(task_executor, surface, surface->IsOffscreen(),
-                       gpu::kNullSurfaceHandle, attributes, limits, nullptr,
-                       nullptr, nullptr);
+  context_->Initialize(std::move(task_executor), surface,
+                       surface->IsOffscreen(), gpu::kNullSurfaceHandle,
+                       attributes, limits, nullptr, nullptr, nullptr);
 
   context_->GetImplementation()->SetLostContextCallback(base::BindOnce(
       &AwRenderThreadContextProvider::OnLostContext, base::Unretained(this)));
diff --git a/android_webview/browser/aw_render_thread_context_provider.h b/android_webview/browser/aw_render_thread_context_provider.h
index 4be7a0f..3767baf 100644
--- a/android_webview/browser/aw_render_thread_context_provider.h
+++ b/android_webview/browser/aw_render_thread_context_provider.h
@@ -36,7 +36,7 @@
  public:
   static scoped_refptr<AwRenderThreadContextProvider> Create(
       scoped_refptr<gl::GLSurface> surface,
-      gpu::CommandBufferTaskExecutor* task_executor);
+      scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor);
 
   // Gives the GL internal format that should be used for calling CopyTexImage2D
   // on the default framebuffer.
@@ -60,8 +60,9 @@
  protected:
   friend class base::RefCountedThreadSafe<AwRenderThreadContextProvider>;
 
-  AwRenderThreadContextProvider(scoped_refptr<gl::GLSurface> surface,
-                                gpu::CommandBufferTaskExecutor* task_executor);
+  AwRenderThreadContextProvider(
+      scoped_refptr<gl::GLSurface> surface,
+      scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor);
   ~AwRenderThreadContextProvider() override;
 
  private:
diff --git a/android_webview/browser/aw_safe_browsing_ui_manager.cc b/android_webview/browser/aw_safe_browsing_ui_manager.cc
index fdf15a4..56da07dbb 100644
--- a/android_webview/browser/aw_safe_browsing_ui_manager.cc
+++ b/android_webview/browser/aw_safe_browsing_ui_manager.cc
@@ -4,9 +4,9 @@
 
 #include "android_webview/browser/aw_safe_browsing_ui_manager.h"
 
+#include "android_webview/browser/aw_content_browser_client.h"
 #include "android_webview/browser/aw_safe_browsing_blocking_page.h"
 #include "android_webview/browser/net/aw_url_request_context_getter.h"
-#include "android_webview/common/aw_content_client.h"
 #include "android_webview/common/aw_paths.h"
 #include "base/command_line.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc
index 93031b3..8f0e692 100644
--- a/android_webview/browser/aw_settings.cc
+++ b/android_webview/browser/aw_settings.cc
@@ -22,11 +22,11 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/renderer_preferences.h"
+#include "content/public/common/renderer_preferences_util.h"
 #include "content/public/common/web_preferences.h"
 #include "jni/AwSettings_jni.h"
 #include "net/http/http_util.h"
 #include "services/network/public/cpp/features.h"
-#include "ui/gfx/font_render_params.h"
 
 using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertUTF8ToJavaString;
@@ -39,18 +39,6 @@
 
 namespace {
 
-void PopulateFixedRendererPreferences(RendererPreferences* prefs) {
-  // TODO(boliu): Deduplicate with chrome/ code.
-  static const base::NoDestructor<gfx::FontRenderParams> params(
-      gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr));
-  prefs->should_antialias_text = params->antialiasing;
-  prefs->use_subpixel_positioning = params->subpixel_positioning;
-  prefs->hinting = params->hinting;
-  prefs->use_autohinter = params->autohinter;
-  prefs->use_bitmaps = params->use_bitmaps;
-  prefs->subpixel_rendering = params->subpixel_rendering;
-}
-
 void PopulateFixedWebPreferences(WebPreferences* web_prefs) {
   web_prefs->shrinks_standalone_images_to_fit = false;
   web_prefs->should_clear_document_background = false;
@@ -171,8 +159,7 @@
     web_contents()->SetUserAgentOverride(override, true);
   }
 
-  const content::NavigationController& controller =
-      web_contents()->GetController();
+  content::NavigationController& controller = web_contents()->GetController();
   for (int i = 0; i < controller.GetEntryCount(); ++i)
     controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(ua_overidden);
 }
@@ -233,7 +220,7 @@
   RendererPreferences* prefs = web_contents()->GetMutableRendererPrefs();
 
   if (!renderer_prefs_initialized_) {
-    PopulateFixedRendererPreferences(prefs);
+    content::UpdateFontRendererPreferencesFromSystemSettings(prefs);
     renderer_prefs_initialized_ = true;
     update_prefs = true;
   }
@@ -502,8 +489,7 @@
 }
 
 static ScopedJavaLocalRef<jstring> JNI_AwSettings_GetDefaultUserAgent(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& clazz) {
+    JNIEnv* env) {
   return base::android::ConvertUTF8ToJavaString(env, GetUserAgent());
 }
 
diff --git a/android_webview/browser/aw_variations_service_client.cc b/android_webview/browser/aw_variations_service_client.cc
index 8f1c0fe..a9d8d0c 100644
--- a/android_webview/browser/aw_variations_service_client.cc
+++ b/android_webview/browser/aw_variations_service_client.cc
@@ -50,8 +50,11 @@
   return android_webview::GetChannelOrStable();
 }
 
+// True is the default, but keep this override so we can revert permanent
+// consistency support with a 1-line change.
+// TODO(crbug/866722): Remove this, along with the rest of commit bbac4d2c4c.
 bool AwVariationsServiceClient::GetSupportsPermanentConsistency() {
-  return false;
+  return true;
 }
 
 bool AwVariationsServiceClient::OverridesRestrictParameter(
diff --git a/android_webview/browser/aw_web_contents_delegate.cc b/android_webview/browser/aw_web_contents_delegate.cc
index f2366f9..c0c6604 100644
--- a/android_webview/browser/aw_web_contents_delegate.cc
+++ b/android_webview/browser/aw_web_contents_delegate.cc
@@ -319,7 +319,6 @@
 
 static void JNI_AwWebContentsDelegate_FilesSelectedInChooser(
     JNIEnv* env,
-    const JavaParamRef<jclass>& clazz,
     jint process_id,
     jint render_id,
     jint mode_flags,
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 055c042d..489c7fa 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -107,14 +107,16 @@
       max_page_scale_factor_(0.f),
       on_new_picture_enable_(false),
       clear_view_(false),
-      offscreen_pre_raster_(false) {}
+      offscreen_pre_raster_(false),
+      weak_ptr_factory_(this) {}
 
 BrowserViewRenderer::~BrowserViewRenderer() {
   DCHECK(compositor_map_.empty());
-  SetCurrentCompositorFrameConsumer(nullptr);
-  while (compositor_frame_consumers_.size()) {
-    RemoveCompositorFrameConsumer(*compositor_frame_consumers_.begin());
-  }
+  DCHECK(!current_compositor_frame_consumer_);
+}
+
+base::WeakPtr<CompositorFrameProducer> BrowserViewRenderer::GetWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
 }
 
 void BrowserViewRenderer::SetCurrentCompositorFrameConsumer(
@@ -124,7 +126,6 @@
   }
   current_compositor_frame_consumer_ = compositor_frame_consumer;
   if (current_compositor_frame_consumer_) {
-    compositor_frame_consumers_.insert(current_compositor_frame_consumer_);
     current_compositor_frame_consumer_->SetCompositorFrameProducer(this);
     OnParentDrawConstraintsUpdated(current_compositor_frame_consumer_);
   }
@@ -209,8 +210,6 @@
   DCHECK(current_compositor_frame_consumer_);
   TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware");
 
-  current_compositor_frame_consumer_->InitializeHardwareDrawIfNeededOnUI();
-
   if (!CanOnDraw()) {
     return false;
   }
@@ -222,7 +221,6 @@
   external_draw_constraints_ =
       current_compositor_frame_consumer_->GetParentDrawConstraintsOnUI();
 
-  ReturnResourceFromParent(current_compositor_frame_consumer_);
   UpdateMemoryPolicy();
 
   gfx::Transform transform_for_tile_priority =
@@ -257,12 +255,6 @@
   return viewport_rect_for_tile_priority;
 }
 
-void BrowserViewRenderer::ReturnedResourceAvailable(
-    CompositorFrameConsumer* compositor_frame_consumer) {
-  DCHECK(compositor_frame_consumers_.count(compositor_frame_consumer));
-  ReturnResourceFromParent(compositor_frame_consumer);
-}
-
 void BrowserViewRenderer::OnParentDrawConstraintsUpdated(
     CompositorFrameConsumer* compositor_frame_consumer) {
   DCHECK(compositor_frame_consumer);
@@ -278,20 +270,10 @@
 }
 
 void BrowserViewRenderer::RemoveCompositorFrameConsumer(
-    CompositorFrameConsumer* compositor_frame_consumer) {
-  DCHECK(compositor_frame_consumers_.count(compositor_frame_consumer));
-  compositor_frame_consumers_.erase(compositor_frame_consumer);
-  if (current_compositor_frame_consumer_ == compositor_frame_consumer) {
+    CompositorFrameConsumer* consumer) {
+  ReturnUncommittedFrames(consumer->PassUncommittedFrameOnUI());
+  if (current_compositor_frame_consumer_ == consumer)
     SetCurrentCompositorFrameConsumer(nullptr);
-  }
-
-  // At this point the compositor frame consumer has to hand back all resources
-  // to the child compositor.
-  compositor_frame_consumer->DeleteHardwareRendererOnUI();
-  ReturnUncommittedFrames(
-      compositor_frame_consumer->PassUncommittedFrameOnUI());
-  ReturnResourceFromParent(compositor_frame_consumer);
-  compositor_frame_consumer->SetCompositorFrameProducer(nullptr);
 }
 
 void BrowserViewRenderer::ReturnUncommittedFrames(
@@ -315,23 +297,14 @@
                                 std::move(resources));
 }
 
-void BrowserViewRenderer::ReturnResourceFromParent(
-    CompositorFrameConsumer* compositor_frame_consumer) {
-  CompositorFrameConsumer::ReturnedResourcesMap returned_resource_map;
-  compositor_frame_consumer->SwapReturnedResourcesOnUI(&returned_resource_map);
-  for (auto& pair : returned_resource_map) {
-    CompositorID compositor_id = pair.first;
-    content::SynchronousCompositor* compositor = FindCompositor(compositor_id);
-    std::vector<viz::ReturnedResource> resources;
-    resources.swap(pair.second.resources);
-
-    if (compositor && !resources.empty()) {
-      compositor->ReturnResources(pair.second.layer_tree_frame_sink_id,
-                                  resources);
-    }
-
-    has_rendered_frame_ = true;
-  }
+void BrowserViewRenderer::ReturnUsedResources(
+    const std::vector<viz::ReturnedResource>& resources,
+    const CompositorID& compositor_id,
+    uint32_t layer_tree_frame_sink_id) {
+  content::SynchronousCompositor* compositor = FindCompositor(compositor_id);
+  if (compositor && !resources.empty())
+    compositor->ReturnResources(layer_tree_frame_sink_id, resources);
+  has_rendered_frame_ = true;
 }
 
 bool BrowserViewRenderer::OnDrawSoftware(SkCanvas* canvas) {
@@ -470,11 +443,9 @@
 }
 
 void BrowserViewRenderer::ReleaseHardware() {
-  for (auto* compositor_frame_consumer : compositor_frame_consumers_) {
+  if (current_compositor_frame_consumer_) {
     ReturnUncommittedFrames(
-        compositor_frame_consumer->PassUncommittedFrameOnUI());
-    ReturnResourceFromParent(compositor_frame_consumer);
-    DCHECK(compositor_frame_consumer->ReturnedResourcesEmptyOnUI());
+        current_compositor_frame_consumer_->PassUncommittedFrameOnUI());
   }
   hardware_enabled_ = false;
   has_rendered_frame_ = false;
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index ebd1893..a825f965 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -141,11 +141,13 @@
   ui::TouchHandleDrawable* CreateDrawable() override;
 
   // CompositorFrameProducer overrides
-  void ReturnedResourceAvailable(
-      CompositorFrameConsumer* compositor_frame_consumer) override;
-  void OnParentDrawConstraintsUpdated(
-      CompositorFrameConsumer* compositor_frame_consumer) override;
+  base::WeakPtr<CompositorFrameProducer> GetWeakPtr() override;
   void RemoveCompositorFrameConsumer(
+      CompositorFrameConsumer* consumer) override;
+  void ReturnUsedResources(const std::vector<viz::ReturnedResource>& resources,
+                           const CompositorID& compositor_id,
+                           uint32_t layer_tree_frame_sink_id) override;
+  void OnParentDrawConstraintsUpdated(
       CompositorFrameConsumer* compositor_frame_consumer) override;
 
   void SetActiveCompositorID(const CompositorID& compositor_id);
@@ -186,7 +188,6 @@
   BrowserViewRendererClient* const client_;
   const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
   CompositorFrameConsumer* current_compositor_frame_consumer_;
-  std::set<CompositorFrameConsumer*> compositor_frame_consumers_;
 
   // The current compositor that's owned by the current RVH.
   content::SynchronousCompositor* compositor_;
@@ -243,6 +244,8 @@
 
   ParentCompositorDrawConstraints external_draw_constraints_;
 
+  base::WeakPtrFactory<CompositorFrameProducer> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserViewRenderer);
 };
 
diff --git a/android_webview/browser/browser_view_renderer_unittest.cc b/android_webview/browser/browser_view_renderer_unittest.cc
index f44b0ea..176a65f 100644
--- a/android_webview/browser/browser_view_renderer_unittest.cc
+++ b/android_webview/browser/browser_view_renderer_unittest.cc
@@ -185,7 +185,7 @@
     on_draw_count_++;
   }
 
-  bool WillDrawOnRT(AwDrawGLInfo* draw_info) override {
+  bool WillDrawOnRT(HardwareRendererDrawParams* params) override {
     if (draw_gl_count_on_rt_ == 1) {
       draw_gl_count_on_rt_++;
       ui_task_runner_->PostTask(FROM_HERE,
@@ -194,15 +194,15 @@
       return false;
     }
 
-    draw_info->width = window_->surface_size().width();
-    draw_info->height = window_->surface_size().height();
-    draw_info->is_layer = false;
+    params->width = window_->surface_size().width();
+    params->height = window_->surface_size().height();
+    params->is_layer = false;
 
     gfx::Transform transform;
     if (draw_gl_count_on_rt_ == 0)
       transform = new_constraints_.transform;
 
-    transform.matrix().asColMajorf(draw_info->transform);
+    transform.matrix().asColMajorf(params->transform);
     return true;
   }
 
@@ -268,15 +268,15 @@
     on_draw_count_++;
   }
 
-  bool WillDrawOnRT(AwDrawGLInfo* draw_info) override {
+  bool WillDrawOnRT(HardwareRendererDrawParams* params) override {
     will_draw_on_rt_count_++;
     // What happens in practice is draw functor is skipped initially since
     // it is offscreen so entirely clipped. Then later, the webview is moved
     // onscreen without another OnDrawon UI thread, and draw functor is called
     // with non-empty clip. Here in the test we pretend this second draw happens
     // immediately.
-    bool result = RenderingTest::WillDrawOnRT(draw_info);
-    assertNonEmptyClip(draw_info);
+    bool result = RenderingTest::WillDrawOnRT(params);
+    assertNonEmptyClip(params);
     return result;
   }
 
@@ -302,10 +302,10 @@
   }
 
  private:
-  void assertNonEmptyClip(AwDrawGLInfo* draw_info) {
-    gfx::Rect clip(draw_info->clip_left, draw_info->clip_top,
-                   draw_info->clip_right - draw_info->clip_left,
-                   draw_info->clip_bottom - draw_info->clip_top);
+  void assertNonEmptyClip(HardwareRendererDrawParams* params) {
+    gfx::Rect clip(params->clip_left, params->clip_top,
+                   params->clip_right - params->clip_left,
+                   params->clip_bottom - params->clip_top);
     ASSERT_FALSE(clip.IsEmpty());
   }
 
@@ -500,10 +500,15 @@
   }
 
   void CheckResults() override {
-    GetCompositorFrameConsumer()->DeleteHardwareRendererOnUI();
     window_->Detach();
-    window_.reset();
+    functor_->ReleaseOnUIWithInvoke();
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&SwitchLayerTreeFrameSinkIdTest::PostedCheckResults,
+                       base::Unretained(this)));
+  }
 
+  void PostedCheckResults() {
     // Make sure resources for the last output surface are returned.
     EXPECT_EQ(expected_return_count_,
               GetReturnedResourceCounts()[last_layer_tree_frame_sink_id_]);
@@ -537,8 +542,14 @@
   }
 
   void CheckResults() override {
-    LayerTreeFrameSinkResourceCountMap resource_counts;
     functor_.reset();
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&RenderThreadManagerDeletionTest::PostedCheckResults,
+                       base::Unretained(this)));
+  }
+
+  void PostedCheckResults() {
     // Make sure resources for the last frame are returned.
     EXPECT_EQ(expected_return_count_, GetReturnedResourceCounts());
     EndTest();
@@ -550,6 +561,43 @@
 
 RENDERING_TEST_F(RenderThreadManagerDeletionTest);
 
+class RenderThreadManagerDeletionOnRTTest : public ResourceRenderingTest {
+  std::unique_ptr<content::SynchronousCompositor::Frame> GetFrame(
+      int frame_number) override {
+    if (frame_number > 0) {
+      return nullptr;
+    }
+
+    const uint32_t layer_tree_frame_sink_id = 0u;
+    const viz::ResourceId resource_id =
+        static_cast<viz::ResourceId>(frame_number);
+
+    std::unique_ptr<content::SynchronousCompositor::Frame> frame(
+        new content::SynchronousCompositor::Frame);
+    frame->layer_tree_frame_sink_id = layer_tree_frame_sink_id;
+    frame->frame = ConstructFrame(resource_id);
+    ++expected_return_count_[layer_tree_frame_sink_id][resource_id];
+    return frame;
+  }
+
+  void CheckResults() override {
+    functor_->ReleaseOnUIWithoutInvoke(
+        base::BindOnce(&RenderThreadManagerDeletionOnRTTest::PostedCheckResults,
+                       base::Unretained(this)));
+  }
+
+  void PostedCheckResults() {
+    // Make sure resources for the last frame are returned.
+    EXPECT_EQ(expected_return_count_, GetReturnedResourceCounts());
+    EndTest();
+  }
+
+ private:
+  LayerTreeFrameSinkResourceCountMap expected_return_count_;
+};
+
+RENDERING_TEST_F(RenderThreadManagerDeletionOnRTTest);
+
 class RenderThreadManagerSwitchTest : public ResourceRenderingTest {
   std::unique_ptr<content::SynchronousCompositor::Frame> GetFrame(
       int frame_number) override {
@@ -561,9 +609,8 @@
       case 1: {
         // Switch to new RTM.
         std::unique_ptr<FakeFunctor> functor(new FakeFunctor);
-        functor->Init(window_.get(),
-                      std::make_unique<RenderThreadManager>(
-                          functor.get(), base::ThreadTaskRunnerHandle::Get()));
+        functor->Init(window_.get(), std::make_unique<RenderThreadManager>(
+                                         base::ThreadTaskRunnerHandle::Get()));
         browser_view_renderer_->SetCurrentCompositorFrameConsumer(
             functor->GetCompositorFrameConsumer());
         saved_functor_ = std::move(functor_);
@@ -599,8 +646,14 @@
   }
 
   void CheckResults() override {
-    LayerTreeFrameSinkResourceCountMap resource_counts;
     functor_.reset();
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&RenderThreadManagerSwitchTest::PostedCheckResults,
+                       base::Unretained(this)));
+  }
+
+  void PostedCheckResults() {
     // Make sure resources for all frames are returned.
     EXPECT_EQ(expected_return_count_, GetReturnedResourceCounts());
     EndTest();
diff --git a/android_webview/browser/compositor_frame_consumer.h b/android_webview/browser/compositor_frame_consumer.h
index 4990301..9022083 100644
--- a/android_webview/browser/compositor_frame_consumer.h
+++ b/android_webview/browser/compositor_frame_consumer.h
@@ -5,11 +5,8 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_COMPOSITOR_FRAME_CONSUMER_H_
 #define ANDROID_WEBVIEW_BROWSER_COMPOSITOR_FRAME_CONSUMER_H_
 
-#include <map>
-
 #include "android_webview/browser/child_frame.h"
 #include "android_webview/browser/parent_compositor_draw_constraints.h"
-#include "components/viz/common/resources/returned_resource.h"
 #include "ui/gfx/geometry/vector2d.h"
 
 namespace android_webview {
@@ -19,16 +16,6 @@
 
 class CompositorFrameConsumer {
  public:
-  struct ReturnedResources {
-    ReturnedResources();
-    ~ReturnedResources();
-
-    uint32_t layer_tree_frame_sink_id;
-    std::vector<viz::ReturnedResource> resources;
-  };
-  using ReturnedResourcesMap =
-      std::map<CompositorID, ReturnedResources, CompositorIDComparator>;
-
   // A CompositorFrameConsumer may be registered with at most one
   // CompositorFrameProducer.
   // The producer is responsible for managing the relationship with its
@@ -42,14 +29,9 @@
   // Returns uncommitted frame to be returned, if any.
   virtual std::unique_ptr<ChildFrame> SetFrameOnUI(
       std::unique_ptr<ChildFrame> frame) = 0;
-  virtual void InitializeHardwareDrawIfNeededOnUI() = 0;
   virtual ParentCompositorDrawConstraints GetParentDrawConstraintsOnUI()
       const = 0;
-  virtual void SwapReturnedResourcesOnUI(
-      ReturnedResourcesMap* returned_resource_map) = 0;
-  virtual bool ReturnedResourcesEmptyOnUI() const = 0;
   virtual ChildFrameQueue PassUncommittedFrameOnUI() = 0;
-  virtual void DeleteHardwareRendererOnUI() = 0;
 
  protected:
   virtual ~CompositorFrameConsumer() {}
diff --git a/android_webview/browser/compositor_frame_producer.h b/android_webview/browser/compositor_frame_producer.h
index 1e33b91..a207c4d 100644
--- a/android_webview/browser/compositor_frame_producer.h
+++ b/android_webview/browser/compositor_frame_producer.h
@@ -5,18 +5,27 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_COMPOSITOR_FRAME_PRODUCER_H_
 #define ANDROID_WEBVIEW_BROWSER_COMPOSITOR_FRAME_PRODUCER_H_
 
+#include <vector>
+
+#include "android_webview/browser/compositor_id.h"
+#include "base/memory/weak_ptr.h"
+#include "components/viz/common/resources/returned_resource.h"
+
 namespace android_webview {
 
 class CompositorFrameConsumer;
 
 class CompositorFrameProducer {
  public:
-  virtual void ReturnedResourceAvailable(
-      CompositorFrameConsumer* compositor_frame_consumer) = 0;
+  virtual base::WeakPtr<CompositorFrameProducer> GetWeakPtr() = 0;
+  virtual void ReturnUsedResources(
+      const std::vector<viz::ReturnedResource>& resources,
+      const CompositorID& compositor_id,
+      uint32_t layer_tree_frame_sink_id) = 0;
   virtual void OnParentDrawConstraintsUpdated(
       CompositorFrameConsumer* compositor_frame_consumer) = 0;
   virtual void RemoveCompositorFrameConsumer(
-      CompositorFrameConsumer* compositor_frame_consumer) = 0;
+      CompositorFrameConsumer* consumer) = 0;
 
  protected:
   virtual ~CompositorFrameProducer() {}
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc
index 6429bbb..ae12327 100644
--- a/android_webview/browser/cookie_manager.cc
+++ b/android_webview/browser/cookie_manager.cc
@@ -247,7 +247,10 @@
                            base::WaitableEvent::InitialState::NOT_SIGNALED);
   ExecCookieTask(base::BindOnce(
       std::move(task), BoolCallbackAdapter(SignalEventClosure(&completion))));
-  base::ThreadRestrictions::ScopedAllowWait wait;
+
+  // Waiting is necessary when implementing synchronous APIs for the WebView
+  // embedder.
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait;
   completion.Wait();
 }
 
@@ -258,7 +261,7 @@
                            base::WaitableEvent::InitialState::NOT_SIGNALED);
   ExecCookieTask(base::BindOnce(
       std::move(task), IntCallbackAdapter(SignalEventClosure(&completion))));
-  base::ThreadRestrictions::ScopedAllowWait wait;
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait;
   completion.Wait();
 }
 
@@ -270,7 +273,7 @@
                            base::WaitableEvent::InitialState::NOT_SIGNALED);
   ExecCookieTask(
       base::BindOnce(std::move(task), SignalEventClosure(&completion)));
-  base::ThreadRestrictions::ScopedAllowWait wait;
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait;
   completion.Wait();
 }
 
@@ -389,6 +392,8 @@
                                              base::OnceClosure complete) {
   net::CookieOptions options;
   options.set_include_httponly();
+  options.set_same_site_cookie_mode(
+      net::CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
 
   GetCookieStore()->GetCookieListWithOptionsAsync(
       host, options,
diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc
index 046ae3e..056072e 100644
--- a/android_webview/browser/deferred_gpu_command_service.cc
+++ b/android_webview/browser/deferred_gpu_command_service.cc
@@ -4,12 +4,12 @@
 
 #include "android_webview/browser/deferred_gpu_command_service.h"
 
-#include "android_webview/browser/gl_view_renderer_manager.h"
 #include "android_webview/browser/render_thread_manager.h"
+#include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/synchronization/lock.h"
 #include "base/trace_event/trace_event.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/browser/gpu_utils.h"
@@ -38,18 +38,16 @@
 
   DeferredGpuCommandService* service = DeferredGpuCommandService::GetInstance();
   DCHECK(service);
-  service->RunTasks();
+  DCHECK(!service->HasMoreTasks());
 }
 
 ScopedAllowGL::~ScopedAllowGL() {
-  allow_gl.Get().Set(false);
-
   DeferredGpuCommandService* service = DeferredGpuCommandService::GetInstance();
   DCHECK(service);
   service->RunTasks();
-  if (service->IdleQueueSize()) {
-    service->RequestProcessGL(true);
-  }
+  service->PerformAllIdleWork();
+  DCHECK(!service->HasMoreTasks());
+  allow_gl.Get().Set(false);
 }
 
 // gpu::CommandBufferTaskExectuor::Sequence implementation that encapsulates a
@@ -71,10 +69,6 @@
 
   bool ShouldYield() override { return false; }
 
-  // Should not be called because BlockThreadOnWaitSyncToken() returns true,
-  // and the client should not disable sequences to wait for sync tokens.
-  void SetEnabled(bool enabled) override { NOTREACHED(); }
-
   void ScheduleTask(base::OnceClosure task,
                     std::vector<gpu::SyncToken> sync_token_fences) override {
     uint32_t order_num =
@@ -145,8 +139,9 @@
 
 // static
 DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() {
-  static DeferredGpuCommandService* service = CreateDeferredGpuCommandService();
-  return service;
+  static base::NoDestructor<scoped_refptr<DeferredGpuCommandService>> service(
+      CreateDeferredGpuCommandService());
+  return service->get();
 }
 
 DeferredGpuCommandService::DeferredGpuCommandService(
@@ -161,45 +156,25 @@
                                      nullptr,
                                      gl::GLSurfaceFormat()),
       sync_point_manager_(std::move(sync_point_manager)),
-      gpu_info_(gpu_info) {}
-
-DeferredGpuCommandService::~DeferredGpuCommandService() {
-  base::AutoLock lock(tasks_lock_);
-  DCHECK(tasks_.empty());
+      gpu_info_(gpu_info) {
+  DETACH_FROM_THREAD(task_queue_thread_checker_);
 }
 
-// This method can be called on any thread.
-// static
-void DeferredGpuCommandService::RequestProcessGL(bool for_idle) {
-  RenderThreadManager* renderer_state =
-      GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
-  if (!renderer_state) {
-    LOG(ERROR) << "No hardware renderer. Deadlock likely";
-    return;
-  }
-  renderer_state->ClientRequestInvokeGL(for_idle);
+DeferredGpuCommandService::~DeferredGpuCommandService() {
+  DCHECK(tasks_.empty());
 }
 
 // Called from different threads!
 void DeferredGpuCommandService::ScheduleTask(base::OnceClosure task,
                                              bool out_of_order) {
-  {
-    base::AutoLock lock(tasks_lock_);
-    if (out_of_order)
-      tasks_.emplace_front(std::move(task));
-    else
-      tasks_.emplace_back(std::move(task));
-  }
-  if (ScopedAllowGL::IsAllowed()) {
-    RunTasks();
-  } else {
-    RequestProcessGL(false);
-  }
-}
-
-size_t DeferredGpuCommandService::IdleQueueSize() {
-  base::AutoLock lock(tasks_lock_);
-  return idle_tasks_.size();
+  DCHECK_CALLED_ON_VALID_THREAD(task_queue_thread_checker_);
+  LOG_IF(FATAL, !ScopedAllowGL::IsAllowed())
+      << "ScheduleTask outside of ScopedAllowGL";
+  if (out_of_order)
+    tasks_.emplace_front(std::move(task));
+  else
+    tasks_.emplace_back(std::move(task));
+  RunTasks();
 }
 
 std::unique_ptr<gpu::CommandBufferTaskExecutor::Sequence>
@@ -213,44 +188,23 @@
 
 void DeferredGpuCommandService::ScheduleDelayedWork(
     base::OnceClosure callback) {
-  {
-    base::AutoLock lock(tasks_lock_);
-    idle_tasks_.push(std::make_pair(base::Time::Now(), std::move(callback)));
-  }
-  RequestProcessGL(true);
-}
-
-void DeferredGpuCommandService::PerformIdleWork(bool is_idle) {
-  TRACE_EVENT1("android_webview", "DeferredGpuCommandService::PerformIdleWork",
-               "is_idle", is_idle);
-  DCHECK(ScopedAllowGL::IsAllowed());
-  static const base::TimeDelta kMaxIdleAge =
-      base::TimeDelta::FromMilliseconds(16);
-
-  const base::Time now = base::Time::Now();
-  size_t queue_size = IdleQueueSize();
-  while (queue_size--) {
-    base::OnceClosure task;
-    {
-      base::AutoLock lock(tasks_lock_);
-      if (!is_idle) {
-        // Only run old tasks if we are not really idle right now.
-        base::TimeDelta age(now - idle_tasks_.front().first);
-        if (age < kMaxIdleAge)
-          break;
-      }
-      task = std::move(idle_tasks_.front().second);
-      idle_tasks_.pop();
-    }
-    std::move(task).Run();
-  }
+  LOG_IF(FATAL, !ScopedAllowGL::IsAllowed())
+      << "ScheduleDelayedWork outside of ScopedAllowGL";
+  DCHECK_CALLED_ON_VALID_THREAD(task_queue_thread_checker_);
+  idle_tasks_.push(std::make_pair(base::Time::Now(), std::move(callback)));
 }
 
 void DeferredGpuCommandService::PerformAllIdleWork() {
   TRACE_EVENT0("android_webview",
                "DeferredGpuCommandService::PerformAllIdleWork");
-  while (IdleQueueSize()) {
-    PerformIdleWork(true);
+  DCHECK_CALLED_ON_VALID_THREAD(task_queue_thread_checker_);
+  if (inside_run_idle_tasks_)
+    return;
+  base::AutoReset<bool> inside(&inside_run_idle_tasks_, true);
+  while (idle_tasks_.size()) {
+    base::OnceClosure task = std::move(idle_tasks_.front().second);
+    idle_tasks_.pop();
+    std::move(task).Run();
   }
 }
 
@@ -264,29 +218,19 @@
 
 void DeferredGpuCommandService::RunTasks() {
   TRACE_EVENT0("android_webview", "DeferredGpuCommandService::RunTasks");
-  bool has_more_tasks;
-  {
-    base::AutoLock lock(tasks_lock_);
-    has_more_tasks = tasks_.size() > 0;
-  }
-
-  while (has_more_tasks) {
-    base::OnceClosure task;
-    {
-      base::AutoLock lock(tasks_lock_);
-      task = std::move(tasks_.front());
-      tasks_.pop_front();
-    }
-    std::move(task).Run();
-    {
-      base::AutoLock lock(tasks_lock_);
-      has_more_tasks = tasks_.size() > 0;
-    }
+  DCHECK_CALLED_ON_VALID_THREAD(task_queue_thread_checker_);
+  if (inside_run_tasks_)
+    return;
+  base::AutoReset<bool> inside(&inside_run_tasks_, true);
+  while (tasks_.size()) {
+    std::move(tasks_.front()).Run();
+    tasks_.pop_front();
   }
 }
 
-bool DeferredGpuCommandService::BlockThreadOnWaitSyncToken() const {
-  return true;
+bool DeferredGpuCommandService::HasMoreTasks() {
+  DCHECK_CALLED_ON_VALID_THREAD(task_queue_thread_checker_);
+  return tasks_.size() || idle_tasks_.size();
 }
 
 bool DeferredGpuCommandService::CanSupportThreadedTextureMailbox() const {
diff --git a/android_webview/browser/deferred_gpu_command_service.h b/android_webview/browser/deferred_gpu_command_service.h
index a504c76..048ab8d 100644
--- a/android_webview/browser/deferred_gpu_command_service.h
+++ b/android_webview/browser/deferred_gpu_command_service.h
@@ -13,6 +13,7 @@
 #include "base/containers/queue.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
+#include "base/threading/thread_checker.h"
 #include "base/threading/thread_local.h"
 #include "base/time/time.h"
 #include "gpu/config/gpu_info.h"
@@ -46,12 +47,9 @@
  public:
   static DeferredGpuCommandService* GetInstance();
 
-  ~DeferredGpuCommandService() override;
-
   // gpu::CommandBufferTaskExecutor implementation.
   bool ForceVirtualizedGLContexts() const override;
   bool ShouldCreateMemoryTracker() const override;
-  bool BlockThreadOnWaitSyncToken() const override;
   std::unique_ptr<gpu::CommandBufferTaskExecutor::Sequence> CreateSequence()
       override;
   void ScheduleOutOfOrderTask(base::OnceClosure task) override;
@@ -61,20 +59,13 @@
 
   bool CanSupportThreadedTextureMailbox() const;
 
-  // If |is_idle| is false, this will only run older idle tasks.
-  void PerformIdleWork(bool is_idle);
-
-  // Flush the idle queue until it is empty. This is different from
-  // PerformIdleWork(is_idle = true), which does not run any newly scheduled
-  // idle tasks during the idle run.
-  void PerformAllIdleWork();
+ protected:
+  ~DeferredGpuCommandService() override;
 
  private:
   friend class ScopedAllowGL;
   friend class TaskForwardingSequence;
 
-  static void RequestProcessGL(bool for_idle);
-
   DeferredGpuCommandService(
       std::unique_ptr<gpu::SyncPointManager> sync_point_manager,
       const gpu::GpuPreferences& gpu_preferences,
@@ -83,19 +74,26 @@
 
   static DeferredGpuCommandService* CreateDeferredGpuCommandService();
 
-  size_t IdleQueueSize();
+  // Flush the idle queue until it is empty.
+  void PerformAllIdleWork();
 
   // Called by ScopedAllowGL and ScheduleTask().
   void RunTasks();
 
+  bool HasMoreTasks();
+
   // Called by TaskForwardingSequence. |out_of_order| indicates if task should
   // be run ahead of already enqueued tasks.
   void ScheduleTask(base::OnceClosure task, bool out_of_order);
 
-  base::Lock tasks_lock_;
+  // All access to task queue should happen on a single thread.
+  THREAD_CHECKER(task_queue_thread_checker_);
   base::circular_deque<base::OnceClosure> tasks_;
   base::queue<std::pair<base::Time, base::OnceClosure>> idle_tasks_;
 
+  bool inside_run_tasks_ = false;
+  bool inside_run_idle_tasks_ = false;
+
   std::unique_ptr<gpu::SyncPointManager> sync_point_manager_;
   gpu::GPUInfo gpu_info_;
 
diff --git a/android_webview/browser/gl_view_renderer_manager.cc b/android_webview/browser/gl_view_renderer_manager.cc
deleted file mode 100644
index 750846a..0000000
--- a/android_webview/browser/gl_view_renderer_manager.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "android_webview/browser/gl_view_renderer_manager.h"
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/threading/platform_thread.h"
-
-namespace android_webview {
-
-using base::AutoLock;
-
-namespace {
-base::LazyInstance<GLViewRendererManager>::Leaky g_view_renderer_manager =
-    LAZY_INSTANCE_INITIALIZER;
-}  // namespace
-
-// static
-GLViewRendererManager* GLViewRendererManager::GetInstance() {
-  return g_view_renderer_manager.Pointer();
-}
-
-GLViewRendererManager::GLViewRendererManager() {}
-
-GLViewRendererManager::~GLViewRendererManager() {}
-
-GLViewRendererManager::Key GLViewRendererManager::NullKey() {
-  AutoLock auto_lock(lock_);
-  return mru_list_.end();
-}
-
-GLViewRendererManager::Key GLViewRendererManager::PushBack(RendererType view) {
-  AutoLock auto_lock(lock_);
-  DCHECK(!base::ContainsValue(mru_list_, view));
-  mru_list_.push_back(view);
-  Key back = mru_list_.end();
-  back--;
-  return back;
-}
-
-void GLViewRendererManager::DidDrawGL(Key key) {
-  AutoLock auto_lock(lock_);
-  DCHECK(mru_list_.end() != key);
-  mru_list_.splice(mru_list_.begin(), mru_list_, key);
-}
-
-void GLViewRendererManager::Remove(Key key) {
-  AutoLock auto_lock(lock_);
-  DCHECK(mru_list_.end() != key);
-  mru_list_.erase(key);
-}
-
-GLViewRendererManager::RendererType
-GLViewRendererManager::GetMostRecentlyDrawn() const {
-  AutoLock auto_lock(lock_);
-  if (mru_list_.begin() == mru_list_.end())
-    return NULL;
-  return *mru_list_.begin();
-}
-
-}  // namespace android_webview
diff --git a/android_webview/browser/gl_view_renderer_manager.h b/android_webview/browser/gl_view_renderer_manager.h
deleted file mode 100644
index 785f3bef..0000000
--- a/android_webview/browser/gl_view_renderer_manager.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_WEBVIEW_BROWSER_GL_VIEW_RENDERER_MANAGER_H_
-#define ANDROID_WEBVIEW_BROWSER_GL_VIEW_RENDERER_MANAGER_H_
-
-#include <list>
-
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-
-namespace android_webview {
-
-class RenderThreadManager;
-
-class GLViewRendererManager {
- public:
-  typedef RenderThreadManager* RendererType;
-
- private:
-  typedef std::list<RendererType> ListType;
-
- public:
-  typedef ListType::iterator Key;
-
-  static GLViewRendererManager* GetInstance();
-
-  Key NullKey();
-
-  Key PushBack(RendererType view);
-
-  // |key| must be already in manager. Move renderer corresponding to |key| to
-  // most recent.
-  void DidDrawGL(Key key);
-
-  void Remove(Key key);
-
-  RendererType GetMostRecentlyDrawn() const;
-
- private:
-  friend struct base::LazyInstanceTraitsBase<GLViewRendererManager>;
-
-  GLViewRendererManager();
-  ~GLViewRendererManager();
-
-  mutable base::Lock lock_;
-  ListType mru_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(GLViewRendererManager);
-};
-
-}  // namespace android_webview
-
-#endif  // ANDROID_WEBVIEW_BROWSER_GL_VIEW_RENDERER_MANAGER_H_
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index 410c03d..10b51a1 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -12,7 +12,6 @@
 #include "android_webview/browser/parent_compositor_draw_constraints.h"
 #include "android_webview/browser/render_thread_manager.h"
 #include "android_webview/browser/surfaces_instance.h"
-#include "android_webview/public/browser/draw_gl.h"
 #include "base/trace_event/trace_event.h"
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
@@ -77,7 +76,7 @@
   child_frame_queue_.emplace_back(std::move(child_frames.front()));
 }
 
-void HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info) {
+void HardwareRenderer::DrawGL(HardwareRendererDrawParams* params) {
   TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL");
 
   for (auto& pruned_frame : WaitAndPruneFrameQueue(&child_frame_queue_))
@@ -137,15 +136,15 @@
   }
 
   gfx::Transform transform(gfx::Transform::kSkipInitialization);
-  transform.matrix().setColMajorf(draw_info->transform);
+  transform.matrix().setColMajorf(params->transform);
   transform.Translate(scroll_offset_.x(), scroll_offset_.y());
 
-  gfx::Size viewport(draw_info->width, draw_info->height);
+  gfx::Size viewport(params->width, params->height);
   // Need to post the new transform matrix back to child compositor
   // because there is no onDraw during a Render Thread animation, and child
   // compositor might not have the tiles rasterized as the animation goes on.
-  ParentCompositorDrawConstraints draw_constraints(
-      draw_info->is_layer, transform, viewport.IsEmpty());
+  ParentCompositorDrawConstraints draw_constraints(params->is_layer, transform,
+                                                   viewport.IsEmpty());
   if (!child_frame_.get() || draw_constraints.NeedUpdate(*child_frame_)) {
     render_thread_manager_->PostExternalDrawConstraintsToChildCompositorOnRT(
         draw_constraints);
@@ -154,9 +153,9 @@
   if (!child_id_.is_valid())
     return;
 
-  gfx::Rect clip(draw_info->clip_left, draw_info->clip_top,
-                 draw_info->clip_right - draw_info->clip_left,
-                 draw_info->clip_bottom - draw_info->clip_top);
+  gfx::Rect clip(params->clip_left, params->clip_top,
+                 params->clip_right - params->clip_left,
+                 params->clip_bottom - params->clip_top);
   surfaces_->DrawAndSwap(viewport, clip, transform, surface_size_,
                          viz::SurfaceId(frame_sink_id_, child_id_),
                          device_scale_factor_);
diff --git a/android_webview/browser/hardware_renderer.h b/android_webview/browser/hardware_renderer.h
index 4271045..1fdcd6b 100644
--- a/android_webview/browser/hardware_renderer.h
+++ b/android_webview/browser/hardware_renderer.h
@@ -14,8 +14,6 @@
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
 
-struct AwDrawGLInfo;
-
 namespace viz {
 class CompositorFrameSinkSupport;
 class ParentLocalSurfaceIdAllocator;
@@ -27,6 +25,17 @@
 class RenderThreadManager;
 class SurfacesInstance;
 
+struct HardwareRendererDrawParams {
+  int clip_left;
+  int clip_top;
+  int clip_right;
+  int clip_bottom;
+  int width;
+  int height;
+  bool is_layer;
+  float transform[16];
+};
+
 class HardwareRenderer : public viz::mojom::CompositorFrameSinkClient {
  public:
   // Two rules:
@@ -44,7 +53,7 @@
   explicit HardwareRenderer(RenderThreadManager* state);
   ~HardwareRenderer() override;
 
-  void DrawGL(AwDrawGLInfo* draw_info);
+  void DrawGL(HardwareRendererDrawParams* params);
   void CommitFrame();
 
  private:
diff --git a/android_webview/browser/icon_helper.h b/android_webview/browser/icon_helper.h
index 194692bb..02213f1 100644
--- a/android_webview/browser/icon_helper.h
+++ b/android_webview/browser/icon_helper.h
@@ -8,8 +8,8 @@
 #include <stdint.h>
 
 #include <string>
+#include <unordered_set>
 
-#include "base/containers/hash_tables.h"
 #include "base/macros.h"
 #include "content/public/browser/reload_type.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -68,7 +68,7 @@
   Listener* listener_;
 
   typedef uint32_t MissingFaviconURLHash;
-  base::hash_set<MissingFaviconURLHash> missing_favicon_urls_;
+  std::unordered_set<MissingFaviconURLHash> missing_favicon_urls_;
 
   DISALLOW_COPY_AND_ASSIGN(IconHelper);
 };
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index d34ffae..02791cb 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -16,7 +16,7 @@
 #include "android_webview/browser/net/aw_request_interceptor.h"
 #include "android_webview/browser/net/aw_url_request_job_factory.h"
 #include "android_webview/browser/net/init_native_callback.h"
-#include "android_webview/browser/net/token_binding_manager.h"
+#include "android_webview/browser/net_helpers.h"
 #include "android_webview/common/aw_content_client.h"
 #include "base/base_paths_android.h"
 #include "base/bind.h"
@@ -43,7 +43,6 @@
 #include "net/cert/cert_verifier.h"
 #include "net/cookies/cookie_store.h"
 #include "net/dns/mapped_host_resolver.h"
-#include "net/extras/sqlite/sqlite_channel_id_store.h"
 #include "net/http/http_auth_filter.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_auth_preferences.h"
@@ -57,7 +56,6 @@
 #include "net/proxy_resolution/proxy_config_service_android.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/next_proto.h"
-#include "net/ssl/channel_id_service.h"
 #include "net/ssl/ssl_config.h"
 #include "net/ssl/ssl_config_service.h"
 #include "net/url_request/data_protocol_handler.h"
@@ -85,6 +83,7 @@
 
 
 const char kProxyServerSwitch[] = "proxy-server";
+const char kProxyBypassListSwitch[] = "proxy-bypass-list";
 
 void ApplyCmdlineOverridesToHostResolver(
     net::MappedHostResolver* host_resolver) {
@@ -192,7 +191,7 @@
       channel_id_path_(channel_id_path),
       net_log_(net_log),
       proxy_config_service_(std::move(config_service)),
-      proxy_config_service_android_(nullptr),
+      proxy_config_service_android_(proxy_config_service_.get()),
       http_user_agent_settings_(new AwHttpUserAgentSettings()) {
   // CreateSystemProxyConfigService for Android must be called on main thread.
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -272,17 +271,6 @@
   builder.set_ftp_enabled(false);  // Android WebView does not support ftp yet.
 #endif
   DCHECK(proxy_config_service_.get());
-  std::unique_ptr<net::ChannelIDService> channel_id_service;
-  if (TokenBindingManager::GetInstance()->is_enabled()) {
-    scoped_refptr<net::SQLiteChannelIDStore> channel_id_db;
-    channel_id_db = new net::SQLiteChannelIDStore(
-        channel_id_path_,
-        base::CreateSequencedTaskRunnerWithTraits(
-            {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
-
-    channel_id_service.reset(new net::ChannelIDService(
-        new net::DefaultChannelIDStore(channel_id_db.get())));
-  }
 
   // Android provides a local HTTP proxy that handles all the proxying.
   // Create the proxy without a resolver since we rely on this local HTTP proxy.
@@ -292,20 +280,24 @@
       *base::CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(kProxyServerSwitch)) {
     std::string proxy = command_line.GetSwitchValueASCII(kProxyServerSwitch);
+    net::ProxyConfig proxy_config;
+    proxy_config.proxy_rules().ParseFromString(proxy);
+    if (command_line.HasSwitch(kProxyBypassListSwitch)) {
+      std::string bypass_list =
+          command_line.GetSwitchValueASCII(kProxyBypassListSwitch);
+      proxy_config.proxy_rules().bypass_rules.ParseFromString(bypass_list);
+    }
+
     builder.set_proxy_resolution_service(
-        net::ProxyResolutionService::CreateFixed(proxy,
-                                                 NO_TRAFFIC_ANNOTATION_YET));
+        net::ProxyResolutionService::CreateFixed(net::ProxyConfigWithAnnotation(
+            proxy_config, NO_TRAFFIC_ANNOTATION_YET)));
   } else {
-    // Retain a pointer to the config proxy service before ownership is passed
-    // on.
-    proxy_config_service_android_ = proxy_config_service_.get();
     builder.set_proxy_resolution_service(
         net::ProxyResolutionService::CreateWithoutProxyResolver(
             std::move(proxy_config_service_), net_log_));
   }
   builder.set_net_log(net_log_);
-  builder.SetCookieAndChannelIdStores(std::make_unique<AwCookieStoreWrapper>(),
-                                      std::move(channel_id_service));
+  builder.SetCookieStore(std::make_unique<AwCookieStoreWrapper>());
 
   net::URLRequestContextBuilder::HttpCacheParams cache_params;
   // Note: we create this as IN_MEMORY when the network service is enabled
@@ -315,7 +307,7 @@
       base::FeatureList::IsEnabled(network::features::kNetworkService)
           ? net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY
           : net::URLRequestContextBuilder::HttpCacheParams::DISK_SIMPLE;
-  cache_params.max_size = 20 * 1024 * 1024;  // 20M
+  cache_params.max_size = GetHttpCacheSize();
   cache_params.path = cache_path_;
   builder.EnableHttpCache(cache_params);
 
@@ -419,21 +411,19 @@
       auth_android_negotiate_account_type_.GetValue());
 }
 
-void AwURLRequestContextGetter::SetProxyOverride(
-    const std::string& host,
-    int port,
-    const std::vector<std::string>& exclusion_list,
+std::string AwURLRequestContextGetter::SetProxyOverride(
+    const std::vector<net::ProxyConfigServiceAndroid::ProxyOverrideRule>&
+        proxy_rules,
+    const std::vector<std::string>& bypass_rules,
     base::OnceClosure callback) {
-  if (proxy_config_service_android_ != NULL) {
-    proxy_config_service_android_->SetProxyOverride(host, port, exclusion_list,
-                                                    std::move(callback));
-  }
+  DCHECK(proxy_config_service_android_ != nullptr);
+  return proxy_config_service_android_->SetProxyOverride(
+      proxy_rules, bypass_rules, std::move(callback));
 }
 
 void AwURLRequestContextGetter::ClearProxyOverride(base::OnceClosure callback) {
-  if (proxy_config_service_android_ != NULL) {
-    proxy_config_service_android_->ClearProxyOverride(std::move(callback));
-  }
+  DCHECK(proxy_config_service_android_ != nullptr);
+  proxy_config_service_android_->ClearProxyOverride(std::move(callback));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/net/aw_url_request_context_getter.h b/android_webview/browser/net/aw_url_request_context_getter.h
index 117bdba..208b298 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.h
+++ b/android_webview/browser/net/aw_url_request_context_getter.h
@@ -13,6 +13,7 @@
 #include "base/single_thread_task_runner.h"
 #include "components/prefs/pref_member.h"
 #include "content/public/browser/browser_context.h"
+#include "net/proxy_resolution/proxy_config_service_android.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_job_factory.h"
 
@@ -52,10 +53,11 @@
       const override;
 
   // Methods to set and clear proxy override
-  void SetProxyOverride(const std::string& host,
-                        int port,
-                        const std::vector<std::string>& exclusion_list,
-                        base::OnceClosure callback);
+  std::string SetProxyOverride(
+      const std::vector<net::ProxyConfigServiceAndroid::ProxyOverrideRule>&
+          proxy_rules,
+      const std::vector<std::string>& bypass_rules,
+      base::OnceClosure callback);
   void ClearProxyOverride(base::OnceClosure callback);
 
  private:
diff --git a/android_webview/browser/net/token_binding_manager.cc b/android_webview/browser/net/token_binding_manager.cc
deleted file mode 100644
index e68acd8..0000000
--- a/android_webview/browser/net/token_binding_manager.cc
+++ /dev/null
@@ -1,124 +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 "android_webview/browser/net/token_binding_manager.h"
-
-#include "android_webview/browser/aw_browser_context.h"
-#include "base/callback_helpers.h"
-#include "base/task/post_task.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/storage_partition.h"
-#include "net/ssl/channel_id_service.h"
-#include "net/ssl/channel_id_store.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace android_webview {
-
-using content::BrowserThread;
-using net::ChannelIDService;
-using net::ChannelIDStore;
-
-namespace {
-
-void CompletionCallback(TokenBindingManager::KeyReadyCallback callback,
-                        ChannelIDService::Request* request,
-                        std::unique_ptr<crypto::ECPrivateKey>* key,
-                        int status) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(std::move(callback), status, base::Owned(key->release())));
-}
-
-void DeletionCompleteCallback(
-    TokenBindingManager::DeletionCompleteCallback callback) {
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(callback));
-}
-
-void GetKeyImpl(const std::string& host,
-                TokenBindingManager::KeyReadyCallback callback,
-                scoped_refptr<net::URLRequestContextGetter> context_getter) {
-  ChannelIDService* service =
-      context_getter->GetURLRequestContext()->channel_id_service();
-  ChannelIDService::Request* request = new ChannelIDService::Request();
-  std::unique_ptr<crypto::ECPrivateKey>* key =
-      new std::unique_ptr<crypto::ECPrivateKey>();
-  // The request will own the callback if the call to service returns
-  // PENDING. The request releases the ownership before calling the callback.
-  // TODO(crbug.com/714018): Update base::Bind here to BindOnce after we update
-  // net::CompletionCallback to support OnceCallback.
-  net::CompletionCallback completion_callback =
-      base::Bind(&CompletionCallback, base::Passed(&callback),
-                 base::Owned(request), base::Owned(key));
-  int status =
-      service->GetOrCreateChannelID(host, key, completion_callback, request);
-  if (status == net::ERR_IO_PENDING) {
-    // The operation is pending, callback will be called async.
-    return;
-  }
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
-                           base::BindOnce(completion_callback, status));
-}
-
-void DeleteKeyImpl(const std::string& host,
-                   TokenBindingManager::DeletionCompleteCallback callback,
-                   scoped_refptr<net::URLRequestContextGetter> context_getter,
-                   bool all) {
-  ChannelIDService* service =
-      context_getter->GetURLRequestContext()->channel_id_service();
-  ChannelIDStore* store = service->GetChannelIDStore();
-  base::OnceClosure completion_callback =
-      base::BindOnce(&DeletionCompleteCallback, std::move(callback));
-  if (all) {
-    store->DeleteAll(
-        base::AdaptCallbackForRepeating(std::move(completion_callback)));
-  } else {
-    store->DeleteChannelID(
-        host, base::AdaptCallbackForRepeating(std::move(completion_callback)));
-  }
-}
-
-}  // namespace
-
-base::LazyInstance<TokenBindingManager>::Leaky g_lazy_instance;
-
-TokenBindingManager* TokenBindingManager::GetInstance() {
-  return g_lazy_instance.Pointer();
-}
-
-TokenBindingManager::TokenBindingManager() : enabled_(false) {}
-
-void TokenBindingManager::GetKey(const std::string& host,
-                                 KeyReadyCallback callback) {
-  scoped_refptr<net::URLRequestContextGetter> context_getter =
-      content::BrowserContext::GetDefaultStoragePartition(
-          AwBrowserContext::GetDefault())->GetURLRequestContext();
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(&GetKeyImpl, host, std::move(callback), context_getter));
-}
-
-void TokenBindingManager::DeleteKey(const std::string& host,
-                                    DeletionCompleteCallback callback) {
-  scoped_refptr<net::URLRequestContextGetter> context_getter =
-      content::BrowserContext::GetDefaultStoragePartition(
-          AwBrowserContext::GetDefault())->GetURLRequestContext();
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(&DeleteKeyImpl, host, std::move(callback), context_getter,
-                     false));
-}
-
-void TokenBindingManager::DeleteAllKeys(DeletionCompleteCallback callback) {
-  scoped_refptr<net::URLRequestContextGetter> context_getter =
-      content::BrowserContext::GetDefaultStoragePartition(
-          AwBrowserContext::GetDefault())->GetURLRequestContext();
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(&DeleteKeyImpl, "", std::move(callback), context_getter,
-                     true));
-}
-
-}  // namespace android_webview
diff --git a/android_webview/browser/net/token_binding_manager.h b/android_webview/browser/net/token_binding_manager.h
deleted file mode 100644
index 3bc0158..0000000
--- a/android_webview/browser/net/token_binding_manager.h
+++ /dev/null
@@ -1,70 +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 ANDROID_WEBVIEW_BROWSER_NET_TOKEN_BINDING_MANAGER_H_
-#define ANDROID_WEBVIEW_BROWSER_NET_TOKEN_BINDING_MANAGER_H_
-
-#include "base/callback.h"
-#include "base/lazy_instance.h"
-#include "crypto/ec_private_key.h"
-
-namespace android_webview {
-
-/**
- * Manages the token binding protocol. Token binding can be enabled/disabled
- * for each browser context, however all webviews share the same browser
- * context. Webview does not expose the browser context to the embedder app.
- * This complicates enabling the protocol since it has to be done very early,
- * while creating the url request context.
- *
- * As a solution TokenBindingManager is set as a singleton (just like its very
- * similar friend cookiemanager). In future, if webview provides multiple
- * browser contexts,  we may move the ownership to AwBrowserContext after
- * deciding how to expose the relationship between "context" and the "context
- * specific settings" such as this.
- */
-class TokenBindingManager {
- public:
-  static TokenBindingManager* GetInstance();
-
-  // Should be called before creating the URLRequestContext (starting
-  // chromium). Otherwise it has no effect.
-  void enable_token_binding() { enabled_ = true; }
-  bool is_enabled() { return enabled_; }
-
-  // The callback to indicate the status for fetching the key. The first
-  // parameter is one of a network error code (see the underlying protocol
-  // implementation for more), and the second parameter is the key. The
-  // key is owned by the callback and be destroyed at the end of the call.
-  using KeyReadyCallback =
-      base::OnceCallback<void(int, crypto::ECPrivateKey* key)>;
-  using DeletionCompleteCallback = base::OnceCallback<void(void)>;
-
-  // Retrieve (or create if not exist) the key for the given host. The callback
-  // is called asynchonously to indicate the status for the key creation and
-  // to provide the key.
-  // This method simply pushes the work to the right thread so see the
-  // underlying implementation for more details.
-  void GetKey(const std::string& host, KeyReadyCallback callback);
-
-  // Deletes the key for the given host.  This method simply pushes the work
-  // to the right thread so see the underlying implementation for more details.
-  void DeleteKey(const std::string& host, DeletionCompleteCallback callback);
-
-  // Deletes all the keys. This method simply pushes the work
-  // to the right thread so see the underlying implementation for more details.
-  void DeleteAllKeys(DeletionCompleteCallback callback);
-
- private:
-  friend struct base::LazyInstanceTraitsBase<TokenBindingManager>;
-
-  TokenBindingManager();
-  ~TokenBindingManager() {}
-
-  bool enabled_;
-};
-
-}  // namespace android_webview
-
-#endif  // ANDROID_WEBVIEW_BROWSER_NET_TOKEN_BINDING_MANAGER_H_
diff --git a/android_webview/browser/net_helpers.cc b/android_webview/browser/net_helpers.cc
index 3ebb56f..7aac105 100644
--- a/android_webview/browser/net_helpers.cc
+++ b/android_webview/browser/net_helpers.cc
@@ -32,4 +32,11 @@
   }
 }
 
+int GetHttpCacheSize() {
+  // This currently returns a constant value, but we may consider deciding cache
+  // size dynamically, since Android provides better support on newer versions
+  // (http://crbug.com/893318).
+  return 20 * 1024 * 1024;  // 20M
+}
+
 }  // namespace android_webview
diff --git a/android_webview/browser/net_helpers.h b/android_webview/browser/net_helpers.h
index 6a82511..501d13c 100644
--- a/android_webview/browser/net_helpers.h
+++ b/android_webview/browser/net_helpers.h
@@ -14,6 +14,10 @@
 // Gets the net-layer load_flags which reflect |client|'s cache mode.
 int GetCacheModeForClient(AwContentsIoThreadClient* client);
 
+// Determines the desired size for WebView's on-disk HttpCache, measured in
+// Bytes.
+int GetHttpCacheSize();
+
 }  // namespace android_webview
 
 #endif  // ANDROID_WEBVIEW_BROWSER_NET_HELPERS_H_
diff --git a/android_webview/browser/net_network_service/android_stream_reader_url_loader.cc b/android_webview/browser/net_network_service/android_stream_reader_url_loader.cc
new file mode 100644
index 0000000..5e36ed0
--- /dev/null
+++ b/android_webview/browser/net_network_service/android_stream_reader_url_loader.cc
@@ -0,0 +1,310 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/net_network_service/android_stream_reader_url_loader.h"
+
+#include "android_webview/browser/input_stream.h"
+#include "android_webview/browser/net/input_stream_reader.h"
+#include "base/callback.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "net/base/io_buffer.h"
+#include "net/http/http_status_code.h"
+#include "net/http/http_util.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+
+namespace android_webview {
+
+namespace {
+
+const char kResponseHeaderViaShouldInterceptRequest[] =
+    "Client-Via: shouldInterceptRequest";
+const char kHTTPOkText[] = "OK";
+const char kHTTPNotFoundText[] = "Not Found";
+
+}  // namespace
+
+// In the case when stream reader related tasks are posted on a dedicated
+// thread they can outlive the loader. This is a wrapper is for holding both
+// InputStream and InputStreamReader to ensure they are still there when the
+// task is run.
+class InputStreamReaderWrapper
+    : public base::RefCountedThreadSafe<InputStreamReaderWrapper> {
+ public:
+  InputStreamReaderWrapper(
+      std::unique_ptr<InputStream> input_stream,
+      std::unique_ptr<InputStreamReader> input_stream_reader)
+      : input_stream_(std::move(input_stream)),
+        input_stream_reader_(std::move(input_stream_reader)) {
+    DCHECK(input_stream_);
+    DCHECK(input_stream_reader_);
+  }
+
+  InputStream* input_stream() { return input_stream_.get(); }
+
+  int Seek(const net::HttpByteRange& byte_range) {
+    return input_stream_reader_->Seek(byte_range);
+  }
+
+  int ReadRawData(net::IOBuffer* buffer, int buffer_size) {
+    return input_stream_reader_->ReadRawData(buffer, buffer_size);
+  }
+
+ private:
+  friend class base::RefCountedThreadSafe<InputStreamReaderWrapper>;
+  ~InputStreamReaderWrapper() {}
+
+  std::unique_ptr<InputStream> input_stream_;
+  std::unique_ptr<InputStreamReader> input_stream_reader_;
+
+  DISALLOW_COPY_AND_ASSIGN(InputStreamReaderWrapper);
+};
+
+class AndroidResponseDelegate
+    : public AndroidStreamReaderURLLoader::ResponseDelegate {
+ public:
+  AndroidResponseDelegate(std::unique_ptr<AwWebResourceResponse> response)
+      : response_(std::move(response)) {}
+  std::unique_ptr<android_webview::InputStream> OpenInputStream(
+      JNIEnv* env) override {
+    return response_->GetInputStream(env);
+  }
+
+ private:
+  std::unique_ptr<AwWebResourceResponse> response_;
+};
+
+AndroidStreamReaderURLLoader::AndroidStreamReaderURLLoader(
+    const network::ResourceRequest& resource_request,
+    network::mojom::URLLoaderClientPtr client,
+    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+    std::unique_ptr<ResponseDelegate> response_delegate)
+    : resource_request_(resource_request),
+      client_(std::move(client)),
+      traffic_annotation_(traffic_annotation),
+      response_delegate_(std::move(response_delegate)),
+      writable_handle_watcher_(FROM_HERE,
+                               mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+                               base::SequencedTaskRunnerHandle::Get()),
+      weak_factory_(this) {
+  // If there is a client error, clean up the request.
+  client_.set_connection_error_handler(
+      base::BindOnce(&AndroidStreamReaderURLLoader::RequestComplete,
+                     weak_factory_.GetWeakPtr(), net::ERR_ABORTED));
+}
+
+AndroidStreamReaderURLLoader::~AndroidStreamReaderURLLoader() {}
+
+void AndroidStreamReaderURLLoader::FollowRedirect(
+    const std::vector<std::string>& removed_headers,
+    const net::HttpRequestHeaders& modified_headers,
+    const base::Optional<GURL>& new_url) {}
+void AndroidStreamReaderURLLoader::ProceedWithResponse() {}
+void AndroidStreamReaderURLLoader::SetPriority(net::RequestPriority priority,
+                                               int intra_priority_value) {}
+void AndroidStreamReaderURLLoader::PauseReadingBodyFromNet() {}
+void AndroidStreamReaderURLLoader::ResumeReadingBodyFromNet() {}
+
+void AndroidStreamReaderURLLoader::Start() {
+  if (!ParseRange(resource_request_.headers)) {
+    RequestComplete(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+    return;
+  }
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+  DCHECK(env);
+
+  // TODO(timvolodine): keep the original threading behavior (as in
+  // AndroidStreamReaderURLRequestJob) and open the stream on a dedicated
+  // thread. (crbug.com/913524).
+  std::unique_ptr<InputStream> input_stream =
+      response_delegate_->OpenInputStream(env);
+  OnInputStreamOpened(std::move(input_stream));
+}
+
+void AndroidStreamReaderURLLoader::OnInputStreamOpened(
+    std::unique_ptr<InputStream> input_stream) {
+  if (!input_stream) {
+    // restart not required
+    HeadersComplete(net::HTTP_NOT_FOUND, kHTTPNotFoundText);
+    return;
+  }
+
+  auto input_stream_reader =
+      std::make_unique<InputStreamReader>(input_stream.get());
+  DCHECK(input_stream);
+  DCHECK(!input_stream_reader_wrapper_);
+
+  input_stream_reader_wrapper_ = base::MakeRefCounted<InputStreamReaderWrapper>(
+      std::move(input_stream), std::move(input_stream_reader));
+
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()},
+      base::BindOnce(&InputStreamReaderWrapper::Seek,
+                     input_stream_reader_wrapper_, byte_range_),
+      base::BindOnce(&AndroidStreamReaderURLLoader::OnReaderSeekCompleted,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void AndroidStreamReaderURLLoader::OnReaderSeekCompleted(int result) {
+  if (result >= 0) {
+    // we've got the expected content size here
+    HeadersComplete(net::HTTP_OK, kHTTPOkText);
+  } else {
+    RequestComplete(net::ERR_FAILED);
+  }
+}
+
+// TODO(timvolodine): move this to delegate to make this more generic,
+// to also support streams other than for shouldInterceptRequest.
+void AndroidStreamReaderURLLoader::HeadersComplete(
+    int status_code,
+    const std::string& status_text) {
+  std::string status("HTTP/1.1 ");
+  status.append(base::IntToString(status_code));
+  status.append(" ");
+  status.append(status_text);
+  // HttpResponseHeaders expects its input string to be terminated by two NULs.
+  status.append("\0\0", 2);
+
+  network::ResourceResponseHead head;
+  head.request_start = base::TimeTicks::Now();
+  head.response_start = base::TimeTicks::Now();
+  head.headers = new net::HttpResponseHeaders(status);
+
+  // TODO(timvolodine): add content length header
+  // TODO(timvolodine): add proper mime information
+
+  // Indicate that the response had been obtained via shouldInterceptRequest.
+  head.headers->AddHeader(kResponseHeaderViaShouldInterceptRequest);
+
+  DCHECK(client_.is_bound());
+  client_->OnReceiveResponse(head);
+
+  if (status_code != net::HTTP_OK) {
+    RequestComplete(net::ERR_FAILED);
+    return;
+  }
+
+  SendBody();
+}
+
+void AndroidStreamReaderURLLoader::SendBody() {
+  mojo::ScopedDataPipeConsumerHandle consumer_handle;
+  if (CreateDataPipe(nullptr /*options*/, &producer_handle_,
+                     &consumer_handle) != MOJO_RESULT_OK) {
+    RequestComplete(net::ERR_FAILED);
+    return;
+  }
+  writable_handle_watcher_.Watch(
+      producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+      base::BindRepeating(&AndroidStreamReaderURLLoader::OnDataPipeWritable,
+                          base::Unretained(this)));
+  client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+
+  ReadMore();
+}
+
+void AndroidStreamReaderURLLoader::ReadMore() {
+  DCHECK(!pending_buffer_.get());
+  uint32_t num_bytes;
+  MojoResult mojo_result = network::NetToMojoPendingBuffer::BeginWrite(
+      &producer_handle_, &pending_buffer_, &num_bytes);
+  if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
+    // The pipe is full. We need to wait for it to have more space.
+    writable_handle_watcher_.ArmOrNotify();
+    return;
+  } else if (mojo_result == MOJO_RESULT_FAILED_PRECONDITION) {
+    // The data pipe consumer handle has been closed.
+    RequestComplete(net::ERR_ABORTED);
+    return;
+  } else if (mojo_result != MOJO_RESULT_OK) {
+    // The body stream is in a bad state. Bail out.
+    RequestComplete(net::ERR_UNEXPECTED);
+    return;
+  }
+  scoped_refptr<net::IOBuffer> buffer(
+      new network::NetToMojoIOBuffer(pending_buffer_.get()));
+
+  // TODO(timvolodine): consider using a sequenced task runner.
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()},
+      base::BindOnce(
+          &InputStreamReaderWrapper::ReadRawData, input_stream_reader_wrapper_,
+          base::RetainedRef(buffer.get()), base::checked_cast<int>(num_bytes)),
+      base::BindOnce(&AndroidStreamReaderURLLoader::DidRead,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void AndroidStreamReaderURLLoader::DidRead(int result) {
+  DCHECK(pending_buffer_);
+  if (result < 0) {
+    // error case
+    RequestComplete(result);
+    return;
+  }
+  if (result == 0) {
+    // eof, read completed
+    pending_buffer_->Complete(0);
+    RequestComplete(net::OK);
+    return;
+  }
+  producer_handle_ = pending_buffer_->Complete(result);
+  pending_buffer_ = nullptr;
+
+  // TODO(timvolodine): consider using a sequenced task runner.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&AndroidStreamReaderURLLoader::ReadMore,
+                                weak_factory_.GetWeakPtr()));
+}
+
+void AndroidStreamReaderURLLoader::OnDataPipeWritable(MojoResult result) {
+  if (result == MOJO_RESULT_FAILED_PRECONDITION) {
+    RequestComplete(net::ERR_ABORTED);
+    return;
+  }
+  DCHECK_EQ(result, MOJO_RESULT_OK) << result;
+
+  ReadMore();
+}
+
+void AndroidStreamReaderURLLoader::RequestComplete(int status_code) {
+  client_->OnComplete(network::URLLoaderCompletionStatus(status_code));
+  CleanUp();
+}
+
+void AndroidStreamReaderURLLoader::CleanUp() {
+  // Resets the watchers and pipes, so that we will never be called back.
+  writable_handle_watcher_.Cancel();
+  pending_buffer_ = nullptr;
+  producer_handle_.reset();
+
+  // Manages its own lifetime
+  delete this;
+}
+
+// TODO(timvolodine): consider moving this to the net_helpers.cc
+bool AndroidStreamReaderURLLoader::ParseRange(
+    const net::HttpRequestHeaders& headers) {
+  std::string range_header;
+  if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
+    // This loader only cares about the Range header so that we know how many
+    // bytes in the stream to skip and how many to read after that.
+    std::vector<net::HttpByteRange> ranges;
+    if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+      // In case of multi-range request only use the first range.
+      // We don't support multirange requests.
+      if (ranges.size() == 1)
+        byte_range_ = ranges[0];
+    } else {
+      // This happens if the range header could not be parsed or is invalid.
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/net_network_service/android_stream_reader_url_loader.h b/android_webview/browser/net_network_service/android_stream_reader_url_loader.h
new file mode 100644
index 0000000..1498dc6
--- /dev/null
+++ b/android_webview/browser/net_network_service/android_stream_reader_url_loader.h
@@ -0,0 +1,84 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_NET_NETWORK_SERVICE_ANDROID_STREAM_READER_URL_LOADER_H_
+#define ANDROID_WEBVIEW_BROWSER_NET_NETWORK_SERVICE_ANDROID_STREAM_READER_URL_LOADER_H_
+
+#include "android_webview/browser/net/aw_web_resource_response.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/http/http_byte_range.h"
+#include "services/network/public/cpp/net_adapters.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+
+namespace android_webview {
+
+class InputStream;
+class InputStreamReaderWrapper;
+
+// Custom URLLoader implementation for loading network responses from stream.
+// Current implementation is in particular for supporting shouldInterceptRequest
+// callback in webview.
+class AndroidStreamReaderURLLoader : public network::mojom::URLLoader {
+ public:
+  // Delegate abstraction for obtaining input streams.
+  // TODO(timvolodine): add other methods to this delegate
+  class ResponseDelegate {
+   public:
+    virtual ~ResponseDelegate() {}
+    virtual std::unique_ptr<android_webview::InputStream> OpenInputStream(
+        JNIEnv* env) = 0;
+  };
+
+  AndroidStreamReaderURLLoader(
+      const network::ResourceRequest& resource_request,
+      network::mojom::URLLoaderClientPtr client,
+      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+      std::unique_ptr<ResponseDelegate> response_delegate);
+  ~AndroidStreamReaderURLLoader() override;
+
+  void Start();
+
+  // network::mojom::URLLoader overrides:
+  void FollowRedirect(const std::vector<std::string>& removed_headers,
+                      const net::HttpRequestHeaders& modified_headers,
+                      const base::Optional<GURL>& new_url) override;
+  void ProceedWithResponse() override;
+  void SetPriority(net::RequestPriority priority,
+                   int intra_priority_value) override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
+
+ private:
+  bool ParseRange(const net::HttpRequestHeaders& headers);
+  void OnInputStreamOpened(
+      std::unique_ptr<android_webview::InputStream> input_stream);
+  void OnReaderSeekCompleted(int result);
+  void HeadersComplete(int status_code, const std::string& status_text);
+  void RequestComplete(int status_code);
+  void SendBody();
+
+  void OnDataPipeWritable(MojoResult result);
+  void CleanUp();
+  void DidRead(int result);
+  void ReadMore();
+
+  net::HttpByteRange byte_range_;
+  network::ResourceRequest resource_request_;
+  network::mojom::URLLoaderClientPtr client_;
+  const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
+  std::unique_ptr<ResponseDelegate> response_delegate_;
+  scoped_refptr<InputStreamReaderWrapper> input_stream_reader_wrapper_;
+
+  mojo::ScopedDataPipeProducerHandle producer_handle_;
+  scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_;
+  mojo::SimpleWatcher writable_handle_watcher_;
+
+  base::WeakPtrFactory<AndroidStreamReaderURLLoader> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(AndroidStreamReaderURLLoader);
+};
+
+}  // namespace android_webview
+
+#endif
diff --git a/android_webview/browser/net_network_service/android_stream_reader_url_loader_unittest.cc b/android_webview/browser/net_network_service/android_stream_reader_url_loader_unittest.cc
new file mode 100644
index 0000000..e55f223
--- /dev/null
+++ b/android_webview/browser/net_network_service/android_stream_reader_url_loader_unittest.cc
@@ -0,0 +1,274 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/net_network_service/android_stream_reader_url_loader.h"
+
+#include "android_webview/browser/input_stream.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/public/common/resource_type.h"
+#include "mojo/core/embedder/embedder.h"
+#include "net/http/http_request_headers.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace android_webview {
+
+namespace {
+
+const GURL kTestURL = GURL("https://www.example.com/");
+
+}  // namespace
+
+// Always succeeds, depending on constructor uses the given string as contents
+// for the input stream and puts it in the IOBuffer |nb_reads| times.
+class FakeInputStream : public InputStream {
+ public:
+  explicit FakeInputStream() : contents_(""), nb_reads_(0) {}
+  explicit FakeInputStream(std::string contents)
+      : contents_(contents), nb_reads_(1) {}
+  explicit FakeInputStream(std::string contents, int nb_reads)
+      : contents_(contents), nb_reads_(nb_reads) {}
+  ~FakeInputStream() override {}
+
+  bool BytesAvailable(int* bytes_available) const override { return true; }
+
+  bool Skip(int64_t n, int64_t* bytes_skipped) override {
+    *bytes_skipped = n;
+    return true;
+  }
+
+  bool Read(net::IOBuffer* buf, int length, int* bytes_read) override {
+    if (nb_reads_ <= 0) {
+      *bytes_read = 0;
+      return true;
+    }
+    CHECK_GE(length, static_cast<int>(contents_.length()));
+    memcpy(buf->data(), contents_.c_str(), contents_.length());
+    *bytes_read = contents_.length();
+    buffer_written_ = true;
+    nb_reads_--;
+    return true;
+  }
+
+ private:
+  std::string contents_;
+  bool buffer_written_;
+  int nb_reads_;
+};
+
+// Stream that always fails
+class FakeFailingInputStream : public InputStream {
+ public:
+  FakeFailingInputStream() {}
+  ~FakeFailingInputStream() override {}
+  bool BytesAvailable(int* bytes_available) const override { return false; }
+  bool Skip(int64_t n, int64_t* bytes_skipped) override { return false; }
+  bool Read(net::IOBuffer* dest, int length, int* bytes_read) override {
+    return false;
+  }
+};
+
+class TestResponseDelegate
+    : public AndroidStreamReaderURLLoader::ResponseDelegate {
+ public:
+  TestResponseDelegate(std::unique_ptr<InputStream> input_stream)
+      : input_stream_(std::move(input_stream)) {}
+  ~TestResponseDelegate() override {}
+
+  std::unique_ptr<android_webview::InputStream> OpenInputStream(
+      JNIEnv* env) override {
+    return std::move(input_stream_);
+  }
+
+ private:
+  std::unique_ptr<InputStream> input_stream_;
+};
+
+class AndroidStreamReaderURLLoaderTest : public ::testing::Test {
+ protected:
+  AndroidStreamReaderURLLoaderTest() {}
+  ~AndroidStreamReaderURLLoaderTest() override = default;
+
+  void SetUp() override {
+    mojo::core::Init();
+    feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+  }
+
+  network::ResourceRequest CreateRequest(const GURL& url) {
+    network::ResourceRequest request;
+    request.url = url;
+    request.method = "GET";
+    request.resource_type = content::RESOURCE_TYPE_SUB_RESOURCE;
+    return request;
+  }
+
+  // helper method for creating loaders given a stream
+  AndroidStreamReaderURLLoader* CreateLoader(
+      const network::ResourceRequest& request,
+      network::TestURLLoaderClient* client,
+      std::unique_ptr<InputStream> input_stream) {
+    return new AndroidStreamReaderURLLoader(
+        request, client->CreateInterfacePtr(),
+        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
+        std::make_unique<TestResponseDelegate>(std::move(input_stream)));
+  }
+
+  // Extracts the body data that is present in the consumer pipe
+  // and returns it as a string.
+  std::string ReadAvailableBody(network::TestURLLoaderClient* client) {
+    MojoHandle consumer = client->response_body().value();
+
+    uint32_t num_bytes = 0;
+    MojoReadDataOptions options;
+    options.struct_size = sizeof(options);
+    options.flags = MOJO_READ_DATA_FLAG_QUERY;
+    MojoResult result = MojoReadData(consumer, &options, nullptr, &num_bytes);
+    CHECK_EQ(MOJO_RESULT_OK, result);
+    if (num_bytes == 0)
+      return std::string();
+
+    std::vector<char> buffer(num_bytes);
+    result = MojoReadData(consumer, nullptr, buffer.data(), &num_bytes);
+    CHECK_EQ(MOJO_RESULT_OK, result);
+    CHECK_EQ(num_bytes, buffer.size());
+
+    return std::string(buffer.data(), buffer.size());
+  }
+
+  base::test::ScopedFeatureList feature_list_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  DISALLOW_COPY_AND_ASSIGN(AndroidStreamReaderURLLoaderTest);
+};
+
+// crbug.com/919929
+TEST_F(AndroidStreamReaderURLLoaderTest, DISABLED_ReadFakeStream) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader =
+      CreateLoader(request, client.get(), std::make_unique<FakeInputStream>());
+  loader->Start();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::OK, client->completion_status().error_code);
+  EXPECT_EQ("HTTP/1.1 200 OK",
+            client->response_head().headers->GetStatusLine());
+}
+
+TEST_F(AndroidStreamReaderURLLoaderTest, ReadFailingStream) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader = CreateLoader(
+      request, client.get(), std::make_unique<FakeFailingInputStream>());
+  loader->Start();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code);
+}
+
+// crbug.com/919929
+TEST_F(AndroidStreamReaderURLLoaderTest, DISABLED_ValidRangeRequest) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+  request.headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=10-200");
+
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader =
+      CreateLoader(request, client.get(), std::make_unique<FakeInputStream>());
+  loader->Start();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::OK, client->completion_status().error_code);
+  EXPECT_EQ("HTTP/1.1 200 OK",
+            client->response_head().headers->GetStatusLine());
+}
+
+TEST_F(AndroidStreamReaderURLLoaderTest, InvalidRangeRequest) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+  request.headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=10-0");
+
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader =
+      CreateLoader(request, client.get(), std::make_unique<FakeInputStream>());
+  loader->Start();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+            client->completion_status().error_code);
+}
+
+TEST_F(AndroidStreamReaderURLLoaderTest, NullInputStream) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader =
+      CreateLoader(request, client.get(), nullptr);
+  loader->Start();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code);
+  EXPECT_EQ("HTTP/1.1 404 Not Found",
+            client->response_head().headers->GetStatusLine());
+}
+
+TEST_F(AndroidStreamReaderURLLoaderTest, ReadFakeStreamWithBody) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+
+  std::string expected_body("test");
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader = CreateLoader(
+      request, client.get(), std::make_unique<FakeInputStream>(expected_body));
+  loader->Start();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::OK, client->completion_status().error_code);
+  EXPECT_EQ("HTTP/1.1 200 OK",
+            client->response_head().headers->GetStatusLine());
+  std::string body = ReadAvailableBody(client.get());
+  EXPECT_EQ(expected_body, body);
+}
+
+TEST_F(AndroidStreamReaderURLLoaderTest, ReadFakeStreamWithBodyMultipleReads) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+
+  std::string expected_body("test");
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader =
+      CreateLoader(request, client.get(),
+                   std::make_unique<FakeInputStream>(expected_body, 2));
+  loader->Start();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::OK, client->completion_status().error_code);
+  EXPECT_EQ("HTTP/1.1 200 OK",
+            client->response_head().headers->GetStatusLine());
+  std::string body = ReadAvailableBody(client.get());
+  EXPECT_EQ(expected_body + expected_body, body);
+}
+
+TEST_F(AndroidStreamReaderURLLoaderTest,
+       ReadFakeStreamCloseConsumerPipeDuringResponse) {
+  network::ResourceRequest request = CreateRequest(kTestURL);
+
+  std::string expected_body("test");
+  std::unique_ptr<network::TestURLLoaderClient> client =
+      std::make_unique<network::TestURLLoaderClient>();
+  AndroidStreamReaderURLLoader* loader = CreateLoader(
+      request, client.get(), std::make_unique<FakeInputStream>(expected_body));
+  loader->Start();
+  client->RunUntilResponseBodyArrived();
+  EXPECT_TRUE(client->has_received_response());
+  EXPECT_FALSE(client->has_received_completion());
+  EXPECT_EQ("HTTP/1.1 200 OK",
+            client->response_head().headers->GetStatusLine());
+  auto response_body = client->response_body_release();
+  response_body.reset();
+  client->RunUntilComplete();
+  EXPECT_EQ(net::ERR_ABORTED, client->completion_status().error_code);
+}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/render_thread_manager.cc b/android_webview/browser/render_thread_manager.cc
index 7233bfe5..386e6ca 100644
--- a/android_webview/browser/render_thread_manager.cc
+++ b/android_webview/browser/render_thread_manager.cc
@@ -9,8 +9,6 @@
 #include "android_webview/browser/compositor_frame_producer.h"
 #include "android_webview/browser/compositor_id.h"
 #include "android_webview/browser/deferred_gpu_command_service.h"
-#include "android_webview/browser/hardware_renderer.h"
-#include "android_webview/browser/render_thread_manager_client.h"
 #include "android_webview/browser/scoped_app_gl_state_restore.h"
 #include "android_webview/public/browser/draw_gl.h"
 #include "base/bind.h"
@@ -24,151 +22,31 @@
 
 namespace android_webview {
 
-namespace internal {
-
-class RequestInvokeGLTracker {
- public:
-  RequestInvokeGLTracker();
-  bool ShouldRequestOnNonUiThread(RenderThreadManager* state);
-  bool ShouldRequestOnUiThread(RenderThreadManager* state);
-  void ResetPending();
-  void SetQueuedFunctorOnUi(RenderThreadManager* state);
-
- private:
-  base::Lock lock_;
-  RenderThreadManager* pending_ui_;
-  RenderThreadManager* pending_non_ui_;
-};
-
-RequestInvokeGLTracker::RequestInvokeGLTracker()
-    : pending_ui_(NULL), pending_non_ui_(NULL) {}
-
-bool RequestInvokeGLTracker::ShouldRequestOnNonUiThread(
-    RenderThreadManager* state) {
-  base::AutoLock lock(lock_);
-  if (pending_ui_ || pending_non_ui_)
-    return false;
-  pending_non_ui_ = state;
-  return true;
-}
-
-bool RequestInvokeGLTracker::ShouldRequestOnUiThread(
-    RenderThreadManager* state) {
-  base::AutoLock lock(lock_);
-  if (pending_non_ui_) {
-    pending_non_ui_->ResetRequestInvokeGLCallback();
-    pending_non_ui_ = NULL;
-  }
-  // At this time, we could have already called RequestInvokeGL on the UI
-  // thread,
-  // but the corresponding GL mode process hasn't happened yet. In this case,
-  // don't schedule another requestInvokeGL on the UI thread.
-  if (pending_ui_)
-    return false;
-  pending_ui_ = state;
-  return true;
-}
-
-void RequestInvokeGLTracker::ResetPending() {
-  base::AutoLock lock(lock_);
-  pending_non_ui_ = NULL;
-  pending_ui_ = NULL;
-}
-
-void RequestInvokeGLTracker::SetQueuedFunctorOnUi(RenderThreadManager* state) {
-  base::AutoLock lock(lock_);
-  DCHECK(state);
-  pending_ui_ = state;
-  pending_non_ui_ = NULL;
-}
-
-}  // namespace internal
-
-namespace {
-
-base::LazyInstance<internal::RequestInvokeGLTracker>::DestructorAtExit
-    g_request_invoke_gl_tracker = LAZY_INSTANCE_INITIALIZER;
-
-constexpr base::TimeDelta kSlightlyMoreThanOneFrame =
-    base::TimeDelta::FromMilliseconds(17);
-}
-
 RenderThreadManager::RenderThreadManager(
-    RenderThreadManagerClient* client,
     const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop)
     : ui_loop_(ui_loop),
-      client_(client),
-      compositor_frame_producer_(nullptr),
-      has_received_frame_(false),
-      renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()),
-      inside_hardware_release_(false),
+      mark_hardware_release_(false),
       weak_factory_on_ui_thread_(this) {
   DCHECK(ui_loop_->BelongsToCurrentThread());
-  DCHECK(client_);
   ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr();
-  ResetRequestInvokeGLCallback();
 }
 
 RenderThreadManager::~RenderThreadManager() {
-  DCHECK(ui_loop_->BelongsToCurrentThread());
-  if (compositor_frame_producer_) {
-    compositor_frame_producer_->RemoveCompositorFrameConsumer(this);
-  }
   DCHECK(!hardware_renderer_.get());
-}
-
-void RenderThreadManager::ClientRequestInvokeGL(bool for_idle) {
-  if (ui_loop_->BelongsToCurrentThread()) {
-    if (!g_request_invoke_gl_tracker.Get().ShouldRequestOnUiThread(this))
-      return;
-    ClientRequestInvokeGLOnUI();
-  } else {
-    if (!g_request_invoke_gl_tracker.Get().ShouldRequestOnNonUiThread(this))
-      return;
-    base::OnceClosure callback;
-    {
-      base::AutoLock lock(lock_);
-      callback = request_draw_gl_closure_;
-    }
-    // 17ms is slightly longer than a frame, hoping that it will come
-    // after the next frame so that the idle work is taken care of by
-    // the next frame instead.
-    ui_loop_->PostDelayedTask(
-        FROM_HERE, std::move(callback),
-        for_idle ? kSlightlyMoreThanOneFrame : base::TimeDelta());
-  }
-}
-
-void RenderThreadManager::DidInvokeGLProcess() {
-  g_request_invoke_gl_tracker.Get().ResetPending();
-}
-
-void RenderThreadManager::ResetRequestInvokeGLCallback() {
-  DCHECK(ui_loop_->BelongsToCurrentThread());
-  base::AutoLock lock(lock_);
-  request_draw_gl_cancelable_closure_.Reset(base::BindRepeating(
-      &RenderThreadManager::ClientRequestInvokeGLOnUI, base::Unretained(this)));
-  request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
-}
-
-void RenderThreadManager::ClientRequestInvokeGLOnUI() {
-  DCHECK(ui_loop_->BelongsToCurrentThread());
-  ResetRequestInvokeGLCallback();
-  g_request_invoke_gl_tracker.Get().SetQueuedFunctorOnUi(this);
-  if (!client_->RequestInvokeGL(false)) {
-    g_request_invoke_gl_tracker.Get().ResetPending();
-    LOG(ERROR) << "Failed to request GL process. Deadlock likely";
-  }
+  DCHECK(child_frames_.empty());
 }
 
 void RenderThreadManager::UpdateParentDrawConstraintsOnUI() {
   DCHECK(ui_loop_->BelongsToCurrentThread());
-  if (compositor_frame_producer_) {
-    compositor_frame_producer_->OnParentDrawConstraintsUpdated(this);
+  CheckUiCallsAllowed();
+  if (producer_weak_ptr_) {
+    producer_weak_ptr_->OnParentDrawConstraintsUpdated(this);
   }
 }
 
 void RenderThreadManager::SetScrollOffsetOnUI(gfx::Vector2d scroll_offset) {
+  DCHECK(ui_loop_->BelongsToCurrentThread());
+  CheckUiCallsAllowed();
   base::AutoLock lock(lock_);
   scroll_offset_ = scroll_offset;
 }
@@ -180,8 +58,9 @@
 
 std::unique_ptr<ChildFrame> RenderThreadManager::SetFrameOnUI(
     std::unique_ptr<ChildFrame> new_frame) {
+  DCHECK(ui_loop_->BelongsToCurrentThread());
+  CheckUiCallsAllowed();
   DCHECK(new_frame);
-  has_received_frame_ = true;
 
   base::AutoLock lock(lock_);
   if (child_frames_.empty()) {
@@ -207,6 +86,8 @@
 }
 
 ChildFrameQueue RenderThreadManager::PassUncommittedFrameOnUI() {
+  DCHECK(ui_loop_->BelongsToCurrentThread());
+  CheckUiCallsAllowed();
   base::AutoLock lock(lock_);
   for (auto& frame_ptr : child_frames_)
     frame_ptr->WaitOnFutureIfNeeded();
@@ -231,190 +112,80 @@
 
 ParentCompositorDrawConstraints
 RenderThreadManager::GetParentDrawConstraintsOnUI() const {
+  DCHECK(ui_loop_->BelongsToCurrentThread());
+  CheckUiCallsAllowed();
   base::AutoLock lock(lock_);
   return parent_draw_constraints_;
 }
 
 void RenderThreadManager::SetInsideHardwareRelease(bool inside) {
   base::AutoLock lock(lock_);
-  inside_hardware_release_ = inside;
+  mark_hardware_release_ = inside;
 }
 
 bool RenderThreadManager::IsInsideHardwareRelease() const {
   base::AutoLock lock(lock_);
-  return inside_hardware_release_;
+  return mark_hardware_release_;
 }
 
-RenderThreadManager::ReturnedResources::ReturnedResources()
-    : layer_tree_frame_sink_id(0u) {}
-
-RenderThreadManager::ReturnedResources::~ReturnedResources() {}
-
 void RenderThreadManager::InsertReturnedResourcesOnRT(
     const std::vector<viz::ReturnedResource>& resources,
     const CompositorID& compositor_id,
     uint32_t layer_tree_frame_sink_id) {
   if (resources.empty())
     return;
-
-  base::AutoLock lock(lock_);
-  ReturnedResources& returned_resources =
-      returned_resources_map_[compositor_id];
-  if (returned_resources.layer_tree_frame_sink_id != layer_tree_frame_sink_id) {
-    returned_resources.resources.clear();
-  }
-  returned_resources.resources.insert(returned_resources.resources.end(),
-                                      resources.begin(), resources.end());
-  returned_resources.layer_tree_frame_sink_id = layer_tree_frame_sink_id;
-
-  if (!returned_resource_available_pending_) {
-    returned_resource_available_pending_ = true;
-    ui_loop_->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&RenderThreadManager::ReturnedResourceAvailableOnUI,
-                       ui_thread_weak_ptr_),
-        kSlightlyMoreThanOneFrame * 2);
-  }
+  ui_loop_->PostTask(
+      FROM_HERE, base::BindOnce(&CompositorFrameProducer::ReturnUsedResources,
+                                producer_weak_ptr_, resources, compositor_id,
+                                layer_tree_frame_sink_id));
 }
 
-void RenderThreadManager::ReturnedResourceAvailableOnUI() {
-  bool empty = false;
-  {
-    base::AutoLock lock(lock_);
-    DCHECK(returned_resource_available_pending_);
-    returned_resource_available_pending_ = false;
-    empty = returned_resources_map_.empty();
-  }
-  if (!empty && compositor_frame_producer_) {
-    compositor_frame_producer_->ReturnedResourceAvailable(this);
-  }
+void RenderThreadManager::CommitFrameOnRT() {
+  if (hardware_renderer_)
+    hardware_renderer_->CommitFrame();
 }
 
-void RenderThreadManager::SwapReturnedResourcesOnUI(
-    ReturnedResourcesMap* returned_resource_map) {
-  DCHECK(returned_resource_map->empty());
-  base::AutoLock lock(lock_);
-  returned_resource_map->swap(returned_resources_map_);
-}
-
-bool RenderThreadManager::ReturnedResourcesEmptyOnUI() const {
-  base::AutoLock lock(lock_);
-  return returned_resources_map_.empty();
-}
-
-void RenderThreadManager::DrawGL(AwDrawGLInfo* draw_info) {
-  TRACE_EVENT0("android_webview,toplevel", "DrawFunctor");
-  if (draw_info->mode == AwDrawGLInfo::kModeSync) {
-    TRACE_EVENT_INSTANT0("android_webview", "kModeSync",
-                         TRACE_EVENT_SCOPE_THREAD);
-    if (hardware_renderer_)
-      hardware_renderer_->CommitFrame();
-    return;
-  }
-
+void RenderThreadManager::DrawOnRT(bool save_restore,
+                                   HardwareRendererDrawParams* params) {
   // Force GL binding init if it's not yet initialized.
   DeferredGpuCommandService::GetInstance();
-
-  // kModeProcessNoContext should never happen because we tear down hardware
-  // in onTrimMemory. However that guarantee is maintained outside of chromium
-  // code. Not notifying shared state in kModeProcessNoContext can lead to
-  // immediate deadlock, which is slightly more catastrophic than leaks or
-  // corruption.
-  if (draw_info->mode == AwDrawGLInfo::kModeProcess ||
-      draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
-    DidInvokeGLProcess();
-  }
-
-  {
-    GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
-    base::AutoLock lock(lock_);
-    if (renderer_manager_key_ != manager->NullKey()) {
-      manager->DidDrawGL(renderer_manager_key_);
-    }
-  }
-
-  ScopedAppGLStateRestore state_restore(
-      draw_info->mode == AwDrawGLInfo::kModeDraw
-          ? ScopedAppGLStateRestore::MODE_DRAW
-          : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT,
-      draw_info->version < 3 /* save_restore */);
+  ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW,
+                                        save_restore);
   ScopedAllowGL allow_gl;
-  if (!hardware_renderer_ && draw_info->mode == AwDrawGLInfo::kModeDraw &&
-      !IsInsideHardwareRelease() && HasFrameForHardwareRendererOnRT()) {
+  if (!hardware_renderer_ && !IsInsideHardwareRelease() &&
+      HasFrameForHardwareRendererOnRT()) {
     hardware_renderer_.reset(new HardwareRenderer(this));
     hardware_renderer_->CommitFrame();
   }
 
-  if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
-    LOG(ERROR) << "Received unexpected kModeProcessNoContext";
-  }
-
-  if (IsInsideHardwareRelease()) {
-    hardware_renderer_.reset();
-    // Flush the idle queue in tear down.
-    DeferredGpuCommandService::GetInstance()->PerformAllIdleWork();
-    return;
-  }
-
-  if (draw_info->mode != AwDrawGLInfo::kModeDraw) {
-    if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
-      DeferredGpuCommandService::GetInstance()->PerformIdleWork(true);
-    }
-    return;
-  }
-
   if (hardware_renderer_)
-    hardware_renderer_->DrawGL(draw_info);
-  DeferredGpuCommandService::GetInstance()->PerformIdleWork(false);
+    hardware_renderer_->DrawGL(params);
 }
 
-void RenderThreadManager::DeleteHardwareRendererOnUI() {
+void RenderThreadManager::DestroyHardwareRendererOnRT(bool save_restore) {
+  DeferredGpuCommandService::GetInstance();
+  ScopedAppGLStateRestore state_restore(
+      ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT, save_restore);
+  ScopedAllowGL allow_gl;
+  hardware_renderer_.reset();
+}
+
+void RenderThreadManager::RemoveFromCompositorFrameProducerOnUI() {
   DCHECK(ui_loop_->BelongsToCurrentThread());
-
-  InsideHardwareReleaseReset auto_inside_hardware_release_reset(this);
-
-  client_->DetachFunctorFromView();
-
-  // If the WebView gets onTrimMemory >= MODERATE twice in a row, the 2nd
-  // onTrimMemory will result in an unnecessary Render Thread InvokeGL call.
-  if (has_received_frame_) {
-    // Receiving at least one frame is a precondition for
-    // initialization (such as looing up GL bindings and constructing
-    // hardware_renderer_).
-    bool draw_functor_succeeded = client_->RequestInvokeGL(true);
-    if (!draw_functor_succeeded) {
-      LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?";
-      // Calling release on wrong thread intentionally.
-      AwDrawGLInfo info;
-      info.mode = AwDrawGLInfo::kModeProcess;
-      DrawGL(&info);
-    }
-  }
-
-  GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
-
-  {
-    base::AutoLock lock(lock_);
-    if (renderer_manager_key_ != manager->NullKey()) {
-      manager->Remove(renderer_manager_key_);
-      renderer_manager_key_ = manager->NullKey();
-    }
-  }
-
-  if (has_received_frame_) {
-    // Flush any invoke functors that's caused by ReleaseHardware.
-    client_->RequestInvokeGL(true);
-  }
-
-  has_received_frame_ = false;
+  CheckUiCallsAllowed();
+  if (producer_weak_ptr_)
+    producer_weak_ptr_->RemoveCompositorFrameConsumer(this);
+  weak_factory_on_ui_thread_.InvalidateWeakPtrs();
+#if DCHECK_IS_ON()
+  ui_calls_allowed_ = false;
+#endif  // DCHECK_IS_ON()
 }
 
 void RenderThreadManager::SetCompositorFrameProducer(
     CompositorFrameProducer* compositor_frame_producer) {
-  DCHECK(compositor_frame_producer == compositor_frame_producer_ ||
-         compositor_frame_producer_ == nullptr ||
-         compositor_frame_producer == nullptr);
-  compositor_frame_producer_ = compositor_frame_producer;
+  DCHECK(ui_loop_->BelongsToCurrentThread());
+  CheckUiCallsAllowed();
+  producer_weak_ptr_ = compositor_frame_producer->GetWeakPtr();
 }
 
 bool RenderThreadManager::HasFrameForHardwareRendererOnRT() const {
@@ -422,16 +193,6 @@
   return !child_frames_.empty();
 }
 
-void RenderThreadManager::InitializeHardwareDrawIfNeededOnUI() {
-  DCHECK(ui_loop_->BelongsToCurrentThread());
-  GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
-
-  base::AutoLock lock(lock_);
-  if (renderer_manager_key_ == manager->NullKey()) {
-    renderer_manager_key_ = manager->PushBack(this);
-  }
-}
-
 RenderThreadManager::InsideHardwareReleaseReset::InsideHardwareReleaseReset(
     RenderThreadManager* render_thread_manager)
     : render_thread_manager_(render_thread_manager) {
diff --git a/android_webview/browser/render_thread_manager.h b/android_webview/browser/render_thread_manager.h
index 909e16f..7ae7aab 100644
--- a/android_webview/browser/render_thread_manager.h
+++ b/android_webview/browser/render_thread_manager.h
@@ -8,58 +8,43 @@
 #include <map>
 
 #include "android_webview/browser/compositor_frame_consumer.h"
-#include "android_webview/browser/gl_view_renderer_manager.h"
+#include "android_webview/browser/hardware_renderer.h"
 #include "android_webview/browser/parent_compositor_draw_constraints.h"
-#include "base/cancelable_callback.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "ui/gfx/geometry/vector2d.h"
 
-struct AwDrawGLInfo;
 namespace android_webview {
 
-namespace internal {
-class RequestInvokeGLTracker;
-}
-
-class RenderThreadManagerClient;
 class ChildFrame;
 class CompositorFrameProducer;
 class HardwareRenderer;
-class InsideHardwareReleaseReset;
 struct CompositorID;
 
 // This class is used to pass data between UI thread and RenderThread.
 class RenderThreadManager : public CompositorFrameConsumer {
  public:
-  RenderThreadManager(
-      RenderThreadManagerClient* client,
+  explicit RenderThreadManager(
       const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop);
   ~RenderThreadManager() override;
 
-  // This function can be called from any thread.
-  void ClientRequestInvokeGL(bool for_idle);
-
   // CompositorFrameConsumer methods.
   void SetCompositorFrameProducer(
       CompositorFrameProducer* compositor_frame_producer) override;
   void SetScrollOffsetOnUI(gfx::Vector2d scroll_offset) override;
   std::unique_ptr<ChildFrame> SetFrameOnUI(
       std::unique_ptr<ChildFrame> frame) override;
-  void InitializeHardwareDrawIfNeededOnUI() override;
   ParentCompositorDrawConstraints GetParentDrawConstraintsOnUI() const override;
-  void SwapReturnedResourcesOnUI(
-      ReturnedResourcesMap* returned_resource_map) override;
-  bool ReturnedResourcesEmptyOnUI() const override;
   ChildFrameQueue PassUncommittedFrameOnUI() override;
-  void DeleteHardwareRendererOnUI() override;
+
+  void RemoveFromCompositorFrameProducerOnUI();
 
   // Render thread methods.
   gfx::Vector2d GetScrollOffsetOnRT();
   ChildFrameQueue PassFramesOnRT();
-  void DrawGL(AwDrawGLInfo* draw_info);
   void PostExternalDrawConstraintsToChildCompositorOnRT(
       const ParentCompositorDrawConstraints& parent_draw_constraints);
   void InsertReturnedResourcesOnRT(
@@ -67,8 +52,11 @@
       const CompositorID& compositor_id,
       uint32_t layer_tree_frame_sink_id);
 
- private:
-  friend class internal::RequestInvokeGLTracker;
+  void CommitFrameOnRT();
+  void DrawOnRT(bool save_restore, HardwareRendererDrawParams* params);
+  void DestroyHardwareRendererOnRT(bool save_restore);
+
+  // May be created on either thread.
   class InsideHardwareReleaseReset {
    public:
     explicit InsideHardwareReleaseReset(
@@ -78,47 +66,45 @@
    private:
     RenderThreadManager* render_thread_manager_;
   };
+
+ private:
   static std::unique_ptr<ChildFrame> GetSynchronousCompositorFrame(
       scoped_refptr<content::SynchronousCompositor::FrameFuture> frame_future,
       std::unique_ptr<ChildFrame> child_frame);
 
   // RT thread method.
-  void DidInvokeGLProcess();
   bool HasFrameForHardwareRendererOnRT() const;
-
-  // UI thread methods.
-  void ResetRequestInvokeGLCallback();
-  void ClientRequestInvokeGLOnUI();
-  void UpdateParentDrawConstraintsOnUI();
-  void ReturnedResourceAvailableOnUI();
   bool IsInsideHardwareRelease() const;
   void SetInsideHardwareRelease(bool inside);
 
+  // UI thread methods.
+  void UpdateParentDrawConstraintsOnUI();
+  void CheckUiCallsAllowed() const {
+#if DCHECK_IS_ON()
+    DCHECK(ui_calls_allowed_);
+#endif  // DCHECK_IS_ON()
+  }
+
   // Accessed by UI thread.
   scoped_refptr<base::SingleThreadTaskRunner> ui_loop_;
-  RenderThreadManagerClient* const client_;
-  CompositorFrameProducer* compositor_frame_producer_;
+  base::WeakPtr<CompositorFrameProducer> producer_weak_ptr_;
   base::WeakPtr<RenderThreadManager> ui_thread_weak_ptr_;
-  base::CancelableClosure request_draw_gl_cancelable_closure_;
-  // Whether any frame has been received on the UI thread by
-  // RenderThreadManager.
-  bool has_received_frame_;
+#if DCHECK_IS_ON()
+  // Becomes false after lifetime of this object transitions from being
+  // shared by both UI and RT, to being owned by a single thread and only RT
+  // methods and destructor are allowed after.
+  bool ui_calls_allowed_ = true;
+#endif  // DCHECK_IS_ON()
 
   // Accessed by RT thread.
   std::unique_ptr<HardwareRenderer> hardware_renderer_;
 
-  // This is accessed by both UI and RT now. TODO(hush): move to RT only.
-  GLViewRendererManager::Key renderer_manager_key_;
-
   // Accessed by both UI and RT thread.
   mutable base::Lock lock_;
   gfx::Vector2d scroll_offset_;
   ChildFrameQueue child_frames_;
-  bool inside_hardware_release_;
+  bool mark_hardware_release_;
   ParentCompositorDrawConstraints parent_draw_constraints_;
-  bool returned_resource_available_pending_ = false;
-  ReturnedResourcesMap returned_resources_map_;
-  base::RepeatingClosure request_draw_gl_closure_;
 
   base::WeakPtrFactory<RenderThreadManager> weak_factory_on_ui_thread_;
 
diff --git a/android_webview/browser/render_thread_manager_client.h b/android_webview/browser/render_thread_manager_client.h
deleted file mode 100644
index 1d05fd1..0000000
--- a/android_webview/browser/render_thread_manager_client.h
+++ /dev/null
@@ -1,28 +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 ANDROID_WEBVIEW_BROWSER_RENDER_THREAD_MANAGER_CLIENT_H_
-#define ANDROID_WEBVIEW_BROWSER_RENDER_THREAD_MANAGER_CLIENT_H_
-
-namespace android_webview {
-
-class RenderThreadManagerClient {
- public:
-  // Request DrawGL to be in called AwDrawGLInfo::kModeProcess type.
-  // |wait_for_completion| will cause the call to block until DrawGL has
-  // happened. The callback may never be made, and the mode may be promoted to
-  // kModeDraw.
-  virtual bool RequestInvokeGL(bool wait_for_completion) = 0;
-
-  // Call postInvalidateOnAnimation for invalidations. This is only used to
-  // synchronize draw functor destruction.
-  virtual void DetachFunctorFromView() = 0;
-
- protected:
-  virtual ~RenderThreadManagerClient() {}
-};
-
-}  // namespace android_webview
-
-#endif  // ANDROID_WEBVIEW_BROWSER_RENDER_THREAD_MANAGER_CLIENT_H_
diff --git a/android_webview/browser/state_serializer.cc b/android_webview/browser/state_serializer.cc
index 9a4289b3f..08ab52e 100644
--- a/android_webview/browser/state_serializer.cc
+++ b/android_webview/browser/state_serializer.cc
@@ -35,14 +35,12 @@
 
 }  // namespace
 
-void WriteToPickle(const content::WebContents& web_contents,
-                   base::Pickle* pickle) {
+void WriteToPickle(content::WebContents& web_contents, base::Pickle* pickle) {
   DCHECK(pickle);
 
   internal::WriteHeaderToPickle(pickle);
 
-  const content::NavigationController& controller =
-      web_contents.GetController();
+  content::NavigationController& controller = web_contents.GetController();
   const int entry_count = controller.GetEntryCount();
   const int selected_entry = controller.GetCurrentEntryIndex();
   DCHECK_GE(entry_count, 0);
@@ -134,13 +132,13 @@
          state_version == internal::AW_STATE_VERSION_DATA_URL;
 }
 
-void WriteNavigationEntryToPickle(const content::NavigationEntry& entry,
+void WriteNavigationEntryToPickle(content::NavigationEntry& entry,
                                   base::Pickle* pickle) {
   WriteNavigationEntryToPickle(AW_STATE_VERSION, entry, pickle);
 }
 
 void WriteNavigationEntryToPickle(uint32_t state_version,
-                                  const content::NavigationEntry& entry,
+                                  content::NavigationEntry& entry,
                                   base::Pickle* pickle) {
   DCHECK(IsSupportedVersion(state_version));
   pickle->WriteString(entry.GetURL().spec());
diff --git a/android_webview/browser/state_serializer.h b/android_webview/browser/state_serializer.h
index a07bbd2..d27800b 100644
--- a/android_webview/browser/state_serializer.h
+++ b/android_webview/browser/state_serializer.h
@@ -29,8 +29,7 @@
 // success.
 
 // Note that |pickle| may be changed even if function returns false.
-void WriteToPickle(const content::WebContents& web_contents,
-                   base::Pickle* pickle);
+void WriteToPickle(content::WebContents& web_contents, base::Pickle* pickle);
 
 // |web_contents| will not be modified if function returns false.
 bool RestoreFromPickle(base::PickleIterator* iterator,
@@ -49,10 +48,10 @@
 uint32_t RestoreHeaderFromPickle(base::PickleIterator* iterator)
     WARN_UNUSED_RESULT;
 bool IsSupportedVersion(uint32_t state_version) WARN_UNUSED_RESULT;
-void WriteNavigationEntryToPickle(const content::NavigationEntry& entry,
+void WriteNavigationEntryToPickle(content::NavigationEntry& entry,
                                   base::Pickle* pickle);
 void WriteNavigationEntryToPickle(uint32_t state_version,
-                                  const content::NavigationEntry& entry,
+                                  content::NavigationEntry& entry,
                                   base::Pickle* pickle);
 bool RestoreNavigationEntryFromPickle(base::PickleIterator* iterator,
                                       content::NavigationEntry* entry)
diff --git a/android_webview/browser/state_serializer_unittest.cc b/android_webview/browser/state_serializer_unittest.cc
index 8348785..5cdf3b6 100644
--- a/android_webview/browser/state_serializer_unittest.cc
+++ b/android_webview/browser/state_serializer_unittest.cc
@@ -62,9 +62,28 @@
   return entry;
 }
 
+class AndroidWebViewStateSerializerTest : public testing::Test {
+ public:
+  AndroidWebViewStateSerializerTest() {
+    content::SetContentClient(&content_client_);
+    content::SetBrowserClientForTesting(&browser_client_);
+  }
+
+  ~AndroidWebViewStateSerializerTest() override {
+    content::SetBrowserClientForTesting(nullptr);
+    content::SetContentClient(nullptr);
+  }
+
+ private:
+  content::ContentClient content_client_;
+  content::ContentBrowserClient browser_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(AndroidWebViewStateSerializerTest);
+};
+
 }  // namespace
 
-TEST(AndroidWebViewStateSerializerTest, TestHeaderSerialization) {
+TEST_F(AndroidWebViewStateSerializerTest, TestHeaderSerialization) {
   base::Pickle pickle;
   internal::WriteHeaderToPickle(&pickle);
 
@@ -73,7 +92,8 @@
   EXPECT_GT(version, 0U);
 }
 
-TEST(AndroidWebViewStateSerializerTest, TestLegacyVersionHeaderSerialization) {
+TEST_F(AndroidWebViewStateSerializerTest,
+       TestLegacyVersionHeaderSerialization) {
   base::Pickle pickle;
   internal::WriteHeaderToPickle(internal::AW_STATE_VERSION_INITIAL, &pickle);
 
@@ -82,8 +102,8 @@
   EXPECT_EQ(version, internal::AW_STATE_VERSION_INITIAL);
 }
 
-TEST(AndroidWebViewStateSerializerTest,
-     TestUnsupportedVersionHeaderSerialization) {
+TEST_F(AndroidWebViewStateSerializerTest,
+       TestUnsupportedVersionHeaderSerialization) {
   base::Pickle pickle;
   internal::WriteHeaderToPickle(20000101, &pickle);
 
@@ -92,13 +112,7 @@
   EXPECT_EQ(version, 0U);
 }
 
-TEST(AndroidWebViewStateSerializerTest, TestNavigationEntrySerialization) {
-  // This is required for NavigationEntry::Create.
-  content::ContentClient content_client;
-  content::SetContentClient(&content_client);
-  content::ContentBrowserClient browser_client;
-  content::SetBrowserClientForTesting(&browser_client);
-
+TEST_F(AndroidWebViewStateSerializerTest, TestNavigationEntrySerialization) {
   std::unique_ptr<content::NavigationEntry> entry(CreateNavigationEntry());
 
   base::Pickle pickle;
@@ -128,14 +142,8 @@
   EXPECT_EQ(entry->GetHttpStatusCode(), copy->GetHttpStatusCode());
 }
 
-TEST(AndroidWebViewStateSerializerTest,
-     TestLegacyNavigationEntrySerialization) {
-  // This is required for NavigationEntry::Create.
-  content::ContentClient content_client;
-  content::SetContentClient(&content_client);
-  content::ContentBrowserClient browser_client;
-  content::SetBrowserClientForTesting(&browser_client);
-
+TEST_F(AndroidWebViewStateSerializerTest,
+       TestLegacyNavigationEntrySerialization) {
   std::unique_ptr<content::NavigationEntry> entry(CreateNavigationEntry());
 
   base::Pickle pickle;
@@ -166,13 +174,7 @@
   EXPECT_EQ(entry->GetHttpStatusCode(), copy->GetHttpStatusCode());
 }
 
-TEST(AndroidWebViewStateSerializerTest, TestEmptyDataURLSerialization) {
-  // This is required for NavigationEntry::Create.
-  content::ContentClient content_client;
-  content::SetContentClient(&content_client);
-  content::ContentBrowserClient browser_client;
-  content::SetBrowserClientForTesting(&browser_client);
-
+TEST_F(AndroidWebViewStateSerializerTest, TestEmptyDataURLSerialization) {
   std::unique_ptr<content::NavigationEntry> entry(
       content::NavigationEntry::Create());
   EXPECT_FALSE(entry->GetDataURLAsString());
@@ -189,13 +191,7 @@
   EXPECT_FALSE(entry->GetDataURLAsString());
 }
 
-TEST(AndroidWebViewStateSerializerTest, TestHugeDataURLSerialization) {
-  // This is required for NavigationEntry::Create.
-  content::ContentClient content_client;
-  content::SetContentClient(&content_client);
-  content::ContentBrowserClient browser_client;
-  content::SetBrowserClientForTesting(&browser_client);
-
+TEST_F(AndroidWebViewStateSerializerTest, TestHugeDataURLSerialization) {
   std::unique_ptr<content::NavigationEntry> entry(
       content::NavigationEntry::Create());
   string huge_data_url(1024 * 1024 * 20 - 1, 'd');
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc
index 0c08c21..8917d97 100644
--- a/android_webview/browser/surfaces_instance.cc
+++ b/android_webview/browser/surfaces_instance.cc
@@ -144,7 +144,8 @@
   surface_quad->SetNew(quad_state, gfx::Rect(quad_state->quad_layer_rect),
                        gfx::Rect(quad_state->quad_layer_rect),
                        viz::SurfaceRange(base::nullopt, child_id),
-                       SK_ColorWHITE, false);
+                       SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false,
+                       /*ignores_input_event=*/false);
 
   viz::CompositorFrame frame;
   // We draw synchronously, so acknowledge a manual BeginFrame.
@@ -153,6 +154,7 @@
   frame.render_pass_list.push_back(std::move(render_pass));
   frame.metadata.device_scale_factor = device_scale_factor;
   frame.metadata.referenced_surfaces = GetChildIdsRanges();
+  frame.metadata.frame_token = ++next_frame_token_;
 
   if (!root_id_allocation_.IsValid() || viewport != surface_size_ ||
       device_scale_factor != device_scale_factor_) {
@@ -208,6 +210,7 @@
       viz::BeginFrameAck::CreateManualAckWithDamage();
   frame.metadata.referenced_surfaces = GetChildIdsRanges();
   frame.metadata.device_scale_factor = device_scale_factor_;
+  frame.metadata.frame_token = ++next_frame_token_;
   support_->SubmitCompositorFrame(root_id_allocation_.local_surface_id(),
                                   std::move(frame));
 }
diff --git a/android_webview/browser/surfaces_instance.h b/android_webview/browser/surfaces_instance.h
index 93aa6f6..834ab5dc 100644
--- a/android_webview/browser/surfaces_instance.h
+++ b/android_webview/browser/surfaces_instance.h
@@ -98,6 +98,7 @@
   viz::LocalSurfaceIdAllocation root_id_allocation_;
   float device_scale_factor_ = 1.0f;
   std::vector<viz::SurfaceId> child_ids_;
+  viz::FrameTokenGenerator next_frame_token_;
 
   // This is owned by |display_|.
   ParentOutputSurface* output_surface_;
diff --git a/android_webview/browser/test/fake_window.cc b/android_webview/browser/test/fake_window.cc
index 943bbb2..be780dce 100644
--- a/android_webview/browser/test/fake_window.cc
+++ b/android_webview/browser/test/fake_window.cc
@@ -75,11 +75,13 @@
 
 void FakeWindow::Detach() {
   CheckCurrentlyOnUIThread();
+  view_->SetCurrentCompositorFrameConsumer(nullptr);
   view_->OnDetachedFromWindow();
 }
 
 void FakeWindow::RequestInvokeGL(FakeFunctor* functor,
                                  bool wait_for_completion) {
+  CreateRenderThreadIfNeeded();
   CheckCurrentlyOnUIThread();
   base::WaitableEvent completion(
       base::WaitableEvent::ResetPolicy::MANUAL,
@@ -213,7 +215,9 @@
 FakeFunctor::FakeFunctor() : window_(nullptr) {}
 
 FakeFunctor::~FakeFunctor() {
-  render_thread_manager_.reset();
+  // Older tests delete functor without bothering to
+  // call either release code path. Release thiings here.
+  ReleaseOnUIWithInvoke();
 }
 
 void FakeFunctor::Init(
@@ -221,36 +225,29 @@
     std::unique_ptr<RenderThreadManager> render_thread_manager) {
   window_ = window;
   render_thread_manager_ = std::move(render_thread_manager);
-  callback_ =
-      base::BindRepeating(&RenderThreadManager::DrawGL,
-                          base::Unretained(render_thread_manager_.get()));
 }
 
 void FakeFunctor::Sync(const gfx::Rect& location,
                        WindowHooks* hooks) {
-  DCHECK(!callback_.is_null());
+  DCHECK(render_thread_manager_);
   committed_location_ = location;
-  AwDrawGLInfo sync_info;
-  sync_info.version = kAwDrawGLInfoVersion;
-  sync_info.mode = AwDrawGLInfo::kModeSync;
   hooks->WillSyncOnRT();
-  callback_.Run(&sync_info);
+  render_thread_manager_->CommitFrameOnRT();
   hooks->DidSyncOnRT();
 }
 
 void FakeFunctor::Draw(WindowHooks* hooks) {
-  DCHECK(!callback_.is_null());
-  AwDrawGLInfo draw_info;
-  draw_info.version = kAwDrawGLInfoVersion;
-  draw_info.mode = AwDrawGLInfo::kModeDraw;
-  draw_info.clip_left = committed_location_.x();
-  draw_info.clip_top = committed_location_.y();
-  draw_info.clip_right = committed_location_.x() + committed_location_.width();
-  draw_info.clip_bottom =
-      committed_location_.y() + committed_location_.height();
-  if (!hooks->WillDrawOnRT(&draw_info))
+  DCHECK(render_thread_manager_);
+  HardwareRendererDrawParams params{};
+  params.clip_left = committed_location_.x();
+  params.clip_top = committed_location_.y();
+  params.clip_right = committed_location_.x() + committed_location_.width();
+  params.clip_bottom = committed_location_.y() + committed_location_.height();
+  params.width = committed_location_.width();
+  params.height = committed_location_.height();
+  if (!hooks->WillDrawOnRT(&params))
     return;
-  callback_.Run(&draw_info);
+  render_thread_manager_->DrawOnRT(false /* save_restore */, &params);
   hooks->DidDrawOnRT();
 }
 
@@ -258,13 +255,47 @@
   return render_thread_manager_.get();
 }
 
+void FakeFunctor::ReleaseOnUIWithoutInvoke(base::OnceClosure callback) {
+  DCHECK(render_thread_manager_);
+  render_thread_manager_->RemoveFromCompositorFrameProducerOnUI();
+  window_->render_thread_task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &FakeFunctor::ReleaseOnRT, base::Unretained(this),
+          base::BindOnce(
+              base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
+              base::ThreadTaskRunnerHandle::Get(), FROM_HERE,
+              std::move(callback))));
+}
+
+void FakeFunctor::ReleaseOnRT(base::OnceClosure callback) {
+  DCHECK(render_thread_manager_);
+  {
+    RenderThreadManager::InsideHardwareReleaseReset release_reset(
+        render_thread_manager_.get());
+    render_thread_manager_->DestroyHardwareRendererOnRT(
+        false /* save_restore */);
+  }
+  render_thread_manager_.reset();
+  std::move(callback).Run();
+}
+
+void FakeFunctor::ReleaseOnUIWithInvoke() {
+  if (!render_thread_manager_)
+    return;
+  render_thread_manager_->RemoveFromCompositorFrameProducerOnUI();
+  {
+    RenderThreadManager::InsideHardwareReleaseReset release_reset(
+        render_thread_manager_.get());
+    RequestInvokeGL(true);
+  }
+  render_thread_manager_.reset();
+}
+
 void FakeFunctor::Invoke(WindowHooks* hooks) {
-  DCHECK(!callback_.is_null());
-  AwDrawGLInfo invoke_info;
-  invoke_info.version = kAwDrawGLInfoVersion;
-  invoke_info.mode = AwDrawGLInfo::kModeProcess;
+  DCHECK(render_thread_manager_);
   hooks->WillProcessOnRT();
-  callback_.Run(&invoke_info);
+  render_thread_manager_->DestroyHardwareRendererOnRT(false /* save_restore */);
   hooks->DidProcessOnRT();
 }
 
@@ -274,6 +305,4 @@
   return true;
 }
 
-void FakeFunctor::DetachFunctorFromView() {}
-
 }  // namespace android_webview
diff --git a/android_webview/browser/test/fake_window.h b/android_webview/browser/test/fake_window.h
index 3c1576a..7dd90fe 100644
--- a/android_webview/browser/test/fake_window.h
+++ b/android_webview/browser/test/fake_window.h
@@ -7,8 +7,7 @@
 
 #include <map>
 
-#include "android_webview/browser/render_thread_manager_client.h"
-#include "android_webview/public/browser/draw_gl.h"
+#include "android_webview/browser/hardware_renderer.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
@@ -41,7 +40,7 @@
   virtual void DidSyncOnRT() = 0;
   virtual void WillProcessOnRT() = 0;
   virtual void DidProcessOnRT() = 0;
-  virtual bool WillDrawOnRT(AwDrawGLInfo* draw_info) = 0;
+  virtual bool WillDrawOnRT(HardwareRendererDrawParams* params) = 0;
   virtual void DidDrawOnRT() = 0;
 };
 
@@ -59,6 +58,9 @@
   void RequestDrawGL(FakeFunctor* functor);
 
   bool on_draw_hardware_pending() const { return on_draw_hardware_pending_; }
+  scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner() {
+    return render_thread_loop_;
+  }
 
  private:
   class ScopedMakeCurrent;
@@ -98,12 +100,10 @@
   DISALLOW_COPY_AND_ASSIGN(FakeWindow);
 };
 
-class FakeFunctor : public RenderThreadManagerClient {
+class FakeFunctor {
  public:
-  using DrawGLCallback = base::RepeatingCallback<void(AwDrawGLInfo*)>;
-
   FakeFunctor();
-  ~FakeFunctor() override;
+  ~FakeFunctor();
 
   void Init(FakeWindow* window,
             std::unique_ptr<RenderThreadManager> render_thread_manager);
@@ -112,14 +112,15 @@
   void Invoke(WindowHooks* hooks);
 
   CompositorFrameConsumer* GetCompositorFrameConsumer();
+  void ReleaseOnUIWithInvoke();
 
-  // RenderThreadManagerClient overrides
-  bool RequestInvokeGL(bool wait_for_completion) override;
-  void DetachFunctorFromView() override;
+  void ReleaseOnUIWithoutInvoke(base::OnceClosure callback);
 
  private:
+  bool RequestInvokeGL(bool wait_for_completion);
+  void ReleaseOnRT(base::OnceClosure callback);
+
   FakeWindow* window_;
-  DrawGLCallback callback_;
   std::unique_ptr<RenderThreadManager> render_thread_manager_;
   gfx::Rect committed_location_;
 };
diff --git a/android_webview/browser/test/rendering_test.cc b/android_webview/browser/test/rendering_test.cc
index 23eeb78..09ed0f8 100644
--- a/android_webview/browser/test/rendering_test.cc
+++ b/android_webview/browser/test/rendering_test.cc
@@ -70,9 +70,8 @@
   std::unique_ptr<FakeWindow> window(
       new FakeWindow(browser_view_renderer_.get(), this, gfx::Rect(100, 100)));
   functor_.reset(new FakeFunctor);
-  functor_->Init(window.get(),
-                 std::make_unique<RenderThreadManager>(
-                     functor_.get(), base::ThreadTaskRunnerHandle::Get()));
+  functor_->Init(window.get(), std::make_unique<RenderThreadManager>(
+                                   base::ThreadTaskRunnerHandle::Get()));
   browser_view_renderer_->SetCurrentCompositorFrameConsumer(
       functor_->GetCompositorFrameConsumer());
   window_ = std::move(window);
@@ -137,12 +136,12 @@
   compositor_->SetHardwareFrame(0u, ConstructEmptyFrame());
 }
 
-bool RenderingTest::WillDrawOnRT(AwDrawGLInfo* draw_info) {
-  draw_info->width = window_->surface_size().width();
-  draw_info->height = window_->surface_size().height();
-  draw_info->is_layer = false;
+bool RenderingTest::WillDrawOnRT(HardwareRendererDrawParams* params) {
+  params->width = window_->surface_size().width();
+  params->height = window_->surface_size().height();
+  params->is_layer = false;
   gfx::Transform transform;
-  transform.matrix().asColMajorf(draw_info->transform);
+  transform.matrix().asColMajorf(params->transform);
   return true;
 }
 
diff --git a/android_webview/browser/test/rendering_test.h b/android_webview/browser/test/rendering_test.h
index 9708059..5d9f728 100644
--- a/android_webview/browser/test/rendering_test.h
+++ b/android_webview/browser/test/rendering_test.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "android_webview/browser/browser_view_renderer_client.h"
-#include "android_webview/browser/render_thread_manager_client.h"
 #include "android_webview/browser/test/fake_window.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
@@ -66,7 +65,7 @@
   void DidSyncOnRT() override {}
   void WillProcessOnRT() override {}
   void DidProcessOnRT() override {}
-  bool WillDrawOnRT(AwDrawGLInfo* draw_info) override;
+  bool WillDrawOnRT(HardwareRendererDrawParams* params) override;
   void DidDrawOnRT() override {}
 
   virtual void OnParentDrawConstraintsUpdated() {}
@@ -96,8 +95,6 @@
   std::unique_ptr<content::TestSynchronousCompositor> compositor_;
 
  private:
-  void DrawGL(AwDrawGLInfo* aw_draw_gl_info);
-
   const std::unique_ptr<base::MessageLoop> message_loop_;
   base::RunLoop run_loop_;
 
diff --git a/android_webview/browser/token_binding_manager_bridge.cc b/android_webview/browser/token_binding_manager_bridge.cc
deleted file mode 100644
index 73d93f6..0000000
--- a/android_webview/browser/token_binding_manager_bridge.cc
+++ /dev/null
@@ -1,119 +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 "android_webview/browser/net/token_binding_manager.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/bind.h"
-#include "content/public/browser/browser_thread.h"
-#include "crypto/ec_private_key.h"
-#include "jni/AwTokenBindingManager_jni.h"
-#include "net/base/net_errors.h"
-
-using base::android::ConvertJavaStringToUTF8;
-using base::android::JavaParamRef;
-using base::android::ScopedJavaGlobalRef;
-using base::android::ScopedJavaLocalRef;
-using content::BrowserThread;
-
-namespace android_webview {
-
-namespace {
-
-// Provides the key to the Webview client.
-void OnKeyReady(const ScopedJavaGlobalRef<jobject>& callback,
-                int status,
-                crypto::ECPrivateKey* key) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  JNIEnv* env = base::android::AttachCurrentThread();
-
-  if (status != net::OK || !key) {
-    Java_AwTokenBindingManager_onKeyReady(env, callback, nullptr, nullptr);
-    return;
-  }
-
-  std::vector<uint8_t> private_key;
-  key->ExportPrivateKey(&private_key);
-  ScopedJavaLocalRef<jbyteArray> jprivate_key = base::android::ToJavaByteArray(
-      env, private_key.data(), private_key.size());
-
-  std::vector<uint8_t> public_key;
-  key->ExportPublicKey(&public_key);
-  ScopedJavaLocalRef<jbyteArray> jpublic_key =
-      base::android::ToJavaByteArray(env, public_key.data(), public_key.size());
-
-  Java_AwTokenBindingManager_onKeyReady(env, callback, jprivate_key,
-                                        jpublic_key);
-}
-
-// Indicates webview client that key deletion is complete.
-void OnDeletionComplete(const ScopedJavaGlobalRef<jobject>& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (callback.is_null())
-    return;
-  JNIEnv* env = base::android::AttachCurrentThread();
-  Java_AwTokenBindingManager_onDeletionComplete(env, callback);
-}
-
-}  // namespace
-
-static void JNI_AwTokenBindingManager_EnableTokenBinding(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj) {
-  // This needs to be called before starting chromium engine, so no thread
-  // checks for UI.
-  TokenBindingManager::GetInstance()->enable_token_binding();
-}
-
-static void JNI_AwTokenBindingManager_GetTokenBindingKey(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jstring>& host,
-    const JavaParamRef<jobject>& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  // Store the Java callback in a scoped object and give the ownership to
-  // base::Callback
-  ScopedJavaGlobalRef<jobject> j_callback;
-  j_callback.Reset(env, callback);
-
-  TokenBindingManager::KeyReadyCallback key_callback =
-      base::BindOnce(&OnKeyReady, j_callback);
-  TokenBindingManager::GetInstance()->GetKey(ConvertJavaStringToUTF8(env, host),
-                                             std::move(key_callback));
-}
-
-static void JNI_AwTokenBindingManager_DeleteTokenBindingKey(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jstring>& host,
-    const JavaParamRef<jobject>& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  // Store the Java callback in a scoped object and give the ownership to
-  // base::Callback
-  ScopedJavaGlobalRef<jobject> j_callback;
-  j_callback.Reset(env, callback);
-  TokenBindingManager::DeletionCompleteCallback complete_callback =
-      base::BindOnce(&OnDeletionComplete, j_callback);
-  TokenBindingManager::GetInstance()->DeleteKey(
-      ConvertJavaStringToUTF8(env, host), std::move(complete_callback));
-}
-
-static void JNI_AwTokenBindingManager_DeleteAllTokenBindingKeys(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jobject>& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  // Store the Java callback in a scoped object and give the ownership to
-  // base::Callback
-  ScopedJavaGlobalRef<jobject> j_callback;
-  j_callback.Reset(env, callback);
-  TokenBindingManager::DeletionCompleteCallback complete_callback =
-      base::BindOnce(&OnDeletionComplete, j_callback);
-  TokenBindingManager::GetInstance()->DeleteAllKeys(
-      std::move(complete_callback));
-}
-
-}  // namespace android_webview
diff --git a/android_webview/common/aw_content_client.cc b/android_webview/common/aw_content_client.cc
index babb0fe..8831cc7 100644
--- a/android_webview/common/aw_content_client.cc
+++ b/android_webview/common/aw_content_client.cc
@@ -16,7 +16,6 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/simple_connection_filter.h"
-#include "content/public/common/user_agent.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/config/gpu_util.h"
 #include "ipc/ipc_message.h"
@@ -26,21 +25,6 @@
 
 namespace android_webview {
 
-std::string GetProduct() {
-  return version_info::GetProductNameAndVersionForUserAgent();
-}
-
-std::string GetUserAgent() {
-  // "Version/4.0" had been hardcoded in the legacy WebView.
-  std::string product = "Version/4.0 " + GetProduct();
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kUseMobileUserAgent)) {
-    product += " Mobile";
-  }
-  return content::BuildUserAgentFromProductAndExtraOSInfo(
-      product, "; wv", true /* include_android_build_number */);
-}
-
 void AwContentClient::AddAdditionalSchemes(Schemes* schemes) {
   schemes->local_schemes.push_back(url::kContentScheme);
   schemes->secure_schemes.push_back(
@@ -48,14 +32,6 @@
   schemes->allow_non_standard_schemes_in_origins = true;
 }
 
-std::string AwContentClient::GetProduct() const {
-  return android_webview::GetProduct();
-}
-
-std::string AwContentClient::GetUserAgent() const {
-  return android_webview::GetUserAgent();
-}
-
 base::string16 AwContentClient::GetLocalizedString(int message_id) const {
   // TODO(boliu): Used only by WebKit, so only bundle those resources for
   // Android WebView.
@@ -71,6 +47,12 @@
       resource_id, scale_factor);
 }
 
+base::RefCountedMemory* AwContentClient::GetDataResourceBytes(
+    int resource_id) const {
+  return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
+      resource_id);
+}
+
 bool AwContentClient::CanSendWhileSwappedOut(const IPC::Message* message) {
   // For legacy API support we perform a few browser -> renderer synchronous IPC
   // messages that block the browser. However, the synchronous IPC replies might
diff --git a/android_webview/common/aw_content_client.h b/android_webview/common/aw_content_client.h
index dbc3021..f46f756 100644
--- a/android_webview/common/aw_content_client.h
+++ b/android_webview/common/aw_content_client.h
@@ -15,19 +15,15 @@
 
 namespace android_webview {
 
-std::string GetProduct();
-std::string GetUserAgent();
-
 class AwContentClient : public content::ContentClient {
  public:
   // ContentClient implementation.
   void AddAdditionalSchemes(Schemes* schemes) override;
-  std::string GetProduct() const override;
-  std::string GetUserAgent() const override;
   base::string16 GetLocalizedString(int message_id) const override;
   base::StringPiece GetDataResource(
       int resource_id,
       ui::ScaleFactor scale_factor) const override;
+  base::RefCountedMemory* GetDataResourceBytes(int resource_id) const override;
   bool CanSendWhileSwappedOut(const IPC::Message* message) override;
   void SetGpuInfo(const gpu::GPUInfo& gpu_info) override;
   bool UsingSynchronousCompositing() override;
diff --git a/android_webview/common/aw_paths.cc b/android_webview/common/aw_paths.cc
index 99887b2..6b1bc92d 100644
--- a/android_webview/common/aw_paths.cc
+++ b/android_webview/common/aw_paths.cc
@@ -19,7 +19,7 @@
       if (!base::android::GetCacheDirectory(&cur))
         return false;
       cur = cur.Append(FILE_PATH_LITERAL("WebView"))
-                .Append(FILE_PATH_LITERAL("Crash Reports"));
+                .Append(FILE_PATH_LITERAL("Crashpad"));
       break;
     case DIR_SAFE_BROWSING:
       if (!base::android::GetCacheDirectory(&cur))
diff --git a/android_webview/common/crash_reporter/aw_crash_reporter_client.cc b/android_webview/common/crash_reporter/aw_crash_reporter_client.cc
index f961f7d..84f83e9 100644
--- a/android_webview/common/crash_reporter/aw_crash_reporter_client.cc
+++ b/android_webview/common/crash_reporter/aw_crash_reporter_client.cc
@@ -4,70 +4,47 @@
 
 #include "android_webview/common/crash_reporter/aw_crash_reporter_client.h"
 
-#include <random>
+#include <stdint.h>
 
 #include "android_webview/common/aw_channel.h"
 #include "android_webview/common/aw_descriptors.h"
 #include "android_webview/common/aw_paths.h"
+#include "android_webview/common/aw_switches.h"
 #include "android_webview/common/crash_reporter/crash_keys.h"
 #include "base/android/build_info.h"
 #include "base/base_paths_android.h"
-#include "base/debug/crash_logging.h"
-#include "base/debug/dump_without_crashing.h"
-#include "base/files/file_path.h"
+#include "base/command_line.h"
 #include "base/lazy_instance.h"
+#include "base/logging.h"
 #include "base/path_service.h"
 #include "base/scoped_native_library.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
 #include "build/build_config.h"
-#include "components/crash/content/app/breakpad_linux.h"
 #include "components/crash/content/app/crash_reporter_client.h"
+#include "components/crash/content/app/crashpad.h"
 #include "components/version_info/version_info.h"
 #include "components/version_info/version_info_values.h"
-#include "content/public/common/content_switches.h"
 
 namespace android_webview {
 namespace crash_reporter {
 
 namespace {
 
-// TODO(gsennton) lower the following value before pushing to stable:
-const double minidump_generation_user_fraction = 1.0;
-
-// Returns whether the current process should be reporting crashes through
-// minidumps. This function should only be called once per process - the return
-// value might differ between different calls to this function.
-bool is_process_in_crash_reporting_sample() {
-  // TODO(gsennton): update this method to depend on finch when that is
-  // implemented for WebView.
-  base::Time cur_time = base::Time::Now();
-  std::minstd_rand generator(cur_time.ToInternalValue() /* seed */);
-  std::uniform_real_distribution<double> distribution(0.0, 1.0);
-  return minidump_generation_user_fraction > distribution(generator);
-}
-
 class AwCrashReporterClient : public ::crash_reporter::CrashReporterClient {
  public:
-  AwCrashReporterClient()
-      : dump_fd_(kAndroidMinidumpDescriptor),
-        crash_signal_fd_(-1),
-        in_crash_reporting_sample_(is_process_in_crash_reporting_sample()) {}
-
-  // Does not use lock, can only be called immediately after creation.
-  void set_crash_signal_fd(int fd) { crash_signal_fd_ = fd; }
+  AwCrashReporterClient() {}
 
   // crash_reporter::CrashReporterClient implementation.
-  bool UseCrashKeysWhiteList() override { return true; }
-  const char* const* GetCrashKeyWhiteList() override;
-
   bool IsRunningUnattended() override { return false; }
-  bool GetCollectStatsConsent() override;
-  void GetProductNameAndVersion(const char** product_name,
-                                const char** version) override {
-    *product_name = "AndroidWebView";
-    *version = PRODUCT_VERSION;
+  bool GetCollectStatsConsent() override {
+    // TODO(jperaza): Crashpad uses GetCollectStatsConsent() to enable or
+    // disable upload of crash reports. However, Crashpad does not yet support
+    // upload on Android, so this return value currently has no effect and
+    // WebView's own uploader will determine consent before uploading. If and
+    // when Crashpad supports upload on Android, consent can be determined here,
+    // or WebView can continue uploading reports itself.
+    return false;
   }
+
   void GetProductNameAndVersion(std::string* product_name,
                                 std::string* version,
                                 std::string* channel) override {
@@ -76,20 +53,6 @@
     *channel =
         version_info::GetChannelString(android_webview::GetChannelOrStable());
   }
-  // Microdumps are always enabled in WebView builds, conversely to what happens
-  // in the case of the other Chrome for Android builds (where they are enabled
-  // only when NO_UNWIND_TABLES == 1).
-  bool ShouldEnableBreakpadMicrodumps() override { return true; }
-
-  int GetAndroidMinidumpDescriptor() override { return dump_fd_; }
-  int GetAndroidCrashSignalFD() override { return crash_signal_fd_; }
-
-  bool DumpWithoutCrashingToFd(int fd) {
-    // TODO(tobiasjs): figure out what to do with on demand minidump on the
-    // renderer process of webview.
-    breakpad::GenerateMinidumpOnDemandForAndroid(fd);
-    return true;
-  }
 
   bool GetCrashDumpLocation(base::FilePath* crash_dir) override {
     return base::PathService::Get(android_webview::DIR_CRASH_DUMPS, crash_dir);
@@ -107,36 +70,23 @@
     *sanitize_stacks = true;
   }
 
+  unsigned int GetCrashDumpPercentageForWebView() override { return 100; }
+
+  bool GetBrowserProcessType(std::string* ptype) override {
+    *ptype = base::CommandLine::ForCurrentProcess()->HasSwitch(
+                 switches::kWebViewSandboxedRenderer)
+                 ? "browser"
+                 : "webview";
+    return true;
+  }
+
  private:
-  int dump_fd_;
-  int crash_signal_fd_;
-  bool in_crash_reporting_sample_;
   DISALLOW_COPY_AND_ASSIGN(AwCrashReporterClient);
 };
 
-const char* const* AwCrashReporterClient::GetCrashKeyWhiteList() {
-  return crash_keys::kWebViewCrashKeyWhiteList;
-}
-
-bool AwCrashReporterClient::GetCollectStatsConsent() {
-#if defined(GOOGLE_CHROME_BUILD)
-  // TODO(gsennton): Enabling minidump-generation unconditionally means we
-  // will generate minidumps even if the user doesn't consent to minidump
-  // uploads. However, we will check user-consent before uploading any
-  // minidumps, if we do not have user consent we will delete the minidumps.
-  // We should investigate whether we can avoid generating minidumps
-  // altogether if we don't have user consent, see crbug.com/692485
-  return in_crash_reporting_sample_;
-#else
-  return false;
-#endif  // !defined(GOOGLE_CHROME_BUILD)
-}
-
 base::LazyInstance<AwCrashReporterClient>::Leaky g_crash_reporter_client =
     LAZY_INSTANCE_INITIALIZER;
 
-bool g_enabled = false;
-
 #if defined(ARCH_CPU_X86_FAMILY)
 bool SafeToUseSignalHandler() {
   // N+ shared library namespacing means that we are unable to dlopen
@@ -196,11 +146,13 @@
 
 }  // namespace
 
-void EnableCrashReporter(const std::string& process_type, int crash_signal_fd) {
-  if (g_enabled) {
+void EnableCrashReporter(const std::string& process_type) {
+  static bool enabled;
+  if (enabled) {
     NOTREACHED() << "EnableCrashReporter called more than once";
     return;
   }
+  enabled = true;
 
 #if defined(ARCH_CPU_X86_FAMILY)
   if (!SafeToUseSignalHandler()) {
@@ -210,52 +162,13 @@
 #endif
 
   AwCrashReporterClient* client = g_crash_reporter_client.Pointer();
-  if (process_type == switches::kRendererProcess && crash_signal_fd != -1) {
-    client->set_crash_signal_fd(crash_signal_fd);
-  }
   ::crash_reporter::SetCrashReporterClient(client);
-  breakpad::SanitizationInfo sanitization_info;
-  sanitization_info.should_sanitize_dumps = true;
-#if !defined(COMPONENT_BUILD)
-  sanitization_info.skip_dump_if_principal_mapping_not_referenced = true;
-  sanitization_info.address_within_principal_mapping =
-      reinterpret_cast<uintptr_t>(&EnableCrashReporter);
-#endif  // defined(COMPONENT_BUILD)
-
-  bool is_browser_process =
-      process_type.empty() ||
-      process_type == breakpad::kWebViewSingleProcessType ||
-      process_type == breakpad::kBrowserProcessType;
-  if (is_browser_process) {
-    breakpad::InitCrashReporter(process_type, sanitization_info);
-  } else {
-    breakpad::InitNonBrowserCrashReporterForAndroid(process_type,
-                                                    sanitization_info);
-  }
-  g_enabled = true;
+  ::crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
 }
 
 bool GetCrashDumpLocation(base::FilePath* crash_dir) {
   return g_crash_reporter_client.Get().GetCrashDumpLocation(crash_dir);
 }
 
-void AddGpuFingerprintToMicrodumpCrashHandler(
-    const std::string& gpu_fingerprint) {
-  breakpad::AddGpuFingerprintToMicrodumpCrashHandler(gpu_fingerprint);
-}
-
-bool DumpWithoutCrashingToFd(int fd) {
-  ::crash_reporter::SetCrashReporterClient(g_crash_reporter_client.Pointer());
-  return g_crash_reporter_client.Pointer()->DumpWithoutCrashingToFd(fd);
-}
-
-bool IsCrashReporterEnabled() {
-  return breakpad::IsCrashReporterEnabled();
-}
-
-void SuppressDumpGeneration() {
-  breakpad::SuppressDumpGeneration();
-}
-
 }  // namespace crash_reporter
 }  // namespace android_webview
diff --git a/android_webview/common/crash_reporter/aw_crash_reporter_client.h b/android_webview/common/crash_reporter/aw_crash_reporter_client.h
index 63ceef37..05356d9 100644
--- a/android_webview/common/crash_reporter/aw_crash_reporter_client.h
+++ b/android_webview/common/crash_reporter/aw_crash_reporter_client.h
@@ -14,13 +14,9 @@
 namespace android_webview {
 namespace crash_reporter {
 
-void EnableCrashReporter(const std::string& process_type, int crash_signal_fd);
+void EnableCrashReporter(const std::string& process_type);
 bool GetCrashDumpLocation(base::FilePath* crash_dir);
-void AddGpuFingerprintToMicrodumpCrashHandler(
-    const std::string& gpu_fingerprint);
-bool DumpWithoutCrashingToFd(int fd);
-bool IsCrashReporterEnabled();
-void SuppressDumpGeneration();
+
 }  // namespace crash_reporter
 }  // namespace android_webview
 
diff --git a/android_webview/common/crash_reporter/crash_keys.cc b/android_webview/common/crash_reporter/crash_keys.cc
index e300c40..37d7f59 100644
--- a/android_webview/common/crash_reporter/crash_keys.cc
+++ b/android_webview/common/crash_reporter/crash_keys.cc
@@ -4,7 +4,7 @@
 
 #include "android_webview/common/crash_reporter/crash_keys.h"
 
-#include "components/crash/content/app/breakpad_linux.h"
+#include "components/crash/core/common/crash_key.h"
 
 namespace android_webview {
 namespace crash_keys {
@@ -55,7 +55,7 @@
 // clang-format on
 
 void InitCrashKeysForWebViewTesting() {
-  breakpad::InitCrashKeysForTesting();
+  crash_reporter::InitializeCrashKeys();
 }
 
 }  // namespace crash_keys
diff --git a/android_webview/docs/commandline-flags.md b/android_webview/docs/commandline-flags.md
new file mode 100644
index 0000000..6bbad87
--- /dev/null
+++ b/android_webview/docs/commandline-flags.md
@@ -0,0 +1,62 @@
+# Commandline flags
+
+## Applying flags
+
+**Note:** this requires either a `userdebug` or `eng` Android build (you can
+check with `adb shell getprop ro.build.type`). Flags cannot be enabled on
+production builds of Android.
+
+WebView reads flags from a specific file during startup. To enable flags, write
+to the file with:
+
+```sh
+$ # Overwrites all flags (and prints the new flag state):
+$ build/android/adb_system_webview_command_line \
+    --show-composited-layer-borders \
+    --log-net-log=foo.json # Supports multiple flags
+$ # Simply prints the existing flag state):
+$ build/android/adb_system_webview_command_line
+$ # Passing empty string clears all flags:
+$ build/android/adb_system_webview_command_line ""
+```
+
+Or, you can use the `adb` in your `$PATH` like so:
+
+```sh
+$ FLAG_FILE=/data/local/tmp/webview-command-line
+$ adb shell "echo '_ --show-composited-layer-borders' > ${FLAG_FILE}"
+$ # The first token is ignored. We use '_' as a convenient placeholder, but any
+$ # token is acceptable.
+```
+
+**Note:** either set of commands will overwrite existing flags.
+
+### Applying Features with flags
+
+WebView supports the same `--enable-features=feature1,feature2` and
+`--disable-features=feature3,feature4` syntax as the rest of Chromium. You can
+use these like any other flag. Please consult
+[`base/feature_list.h`](https://cs.chromium.org/chromium/src/base/feature_list.h)
+for details.
+
+## Interesting flags
+
+WebView supports any flags supported in any layer we depend on (ex. content).
+Some interesting flags and Features:
+
+ * `--show-composited-layer-borders`
+ * `--enable-features=NetworkService,NetworkServiceInProcess`
+ * `--log-net-log=<filename.json>`
+
+WebView also defines its own flags and Features:
+
+ * [AwSwitches.java](https://cs.chromium.org/chromium/src/android_webview/java/src/org/chromium/android_webview/AwSwitches.java)
+   (and its [native
+   counterpart](https://cs.chromium.org/chromium/src/android_webview/common/aw_switches.h))
+ * [AwFeatureList.java](https://cs.chromium.org/chromium/src/android_webview/java/src/org/chromium/android_webview/AwFeatureList.java)
+   (and its [native
+   counterpart](https://cs.chromium.org/chromium/src/android_webview/browser/aw_feature_list.h))
+
+## Implementation
+
+See [CommandLineUtil.java](https://cs.chromium.org/chromium/src/android_webview/java/src/org/chromium/android_webview/command_line/CommandLineUtil.java).
diff --git a/android_webview/glue/BUILD.gn b/android_webview/glue/BUILD.gn
index e97103b..7035687 100644
--- a/android_webview/glue/BUILD.gn
+++ b/android_webview/glue/BUILD.gn
@@ -27,6 +27,7 @@
     "java/src/com/android/webview/chromium/CallbackConverter.java",
     "java/src/com/android/webview/chromium/ContentSettingsAdapter.java",
     "java/src/com/android/webview/chromium/CookieManagerAdapter.java",
+    "java/src/com/android/webview/chromium/DrawFunctor.java",
     "java/src/com/android/webview/chromium/DrawGLFunctor.java",
     "java/src/com/android/webview/chromium/FontPreloadingWorkaround.java",
     "java/src/com/android/webview/chromium/GeolocationPermissionsAdapter.java",
@@ -44,7 +45,6 @@
     "java/src/com/android/webview/chromium/SharedStatics.java",
     "java/src/com/android/webview/chromium/SharedTracingControllerAdapter.java",
     "java/src/com/android/webview/chromium/SplitApkWorkaround.java",
-    "java/src/com/android/webview/chromium/TokenBindingManagerAdapter.java",
     "java/src/com/android/webview/chromium/TracingControllerAdapter.java",
     "java/src/com/android/webview/chromium/WebBackForwardListChromium.java",
     "java/src/com/android/webview/chromium/WebHistoryItemChromium.java",
@@ -62,6 +62,8 @@
     "java/src/com/android/webview/chromium/WebViewChromiumFactoryProviderForOMR1.java",
     "java/src/com/android/webview/chromium/WebViewChromiumFactoryProviderForP.java",
     "java/src/com/android/webview/chromium/SharedWebViewChromium.java",
+    "java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java",
+    "java/src/com/android/webview/chromium/SharedWebViewRendererClientAdapter.java",
     "java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java",
     "java/src/com/android/webview/chromium/WebViewDatabaseAdapter.java",
     "java/src/com/android/webview/chromium/WebViewDelegateFactory.java",
diff --git a/android_webview/glue/generate_resource_rewriter.gni b/android_webview/glue/generate_resource_rewriter.gni
index f867477..4d9a233 100644
--- a/android_webview/glue/generate_resource_rewriter.gni
+++ b/android_webview/glue/generate_resource_rewriter.gni
@@ -23,7 +23,7 @@
 
   _final_target_name = target_name
   _build_config = "$target_gen_dir/${target_name}.build_config"
-  _build_config_target_name = "${target_name}__build_config"
+  _build_config_target_name = "$target_name$build_config_target_suffix"
   _srcjar = "$target_gen_dir/${target_name}.srcjar"
   write_build_config(_build_config_target_name) {
     possible_config_deps = invoker.deps
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/DrawFunctor.java b/android_webview/glue/java/src/com/android/webview/chromium/DrawFunctor.java
new file mode 100644
index 0000000..6ebd1cb2
--- /dev/null
+++ b/android_webview/glue/java/src/com/android/webview/chromium/DrawFunctor.java
@@ -0,0 +1,12 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package com.android.webview.chromium;
+
+class DrawFunctor {
+    public static long getDrawFnFunctionTable() {
+        return nativeGetFunctionTable();
+    }
+    private static native long nativeGetFunctionTable();
+}
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/GlueApiHelperForN.java b/android_webview/glue/java/src/com/android/webview/chromium/GlueApiHelperForN.java
index 0638724..a9efd2c 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/GlueApiHelperForN.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/GlueApiHelperForN.java
@@ -11,7 +11,6 @@
 import android.os.Build;
 import android.os.UserManager;
 import android.webkit.ServiceWorkerController;
-import android.webkit.TokenBindingService;
 import android.webkit.WebView;
 import android.webkit.WebViewDelegate;
 
@@ -40,16 +39,6 @@
     }
 
     /**
-     * See {@link
-     * TokenBindingManagerAdapter#TokenBindingManagerAdapter(WebViewChromiumFactoryProvider)}, which
-     * was added in N.
-     */
-    public static TokenBindingService createTokenBindingManagerAdapter(
-            WebViewChromiumFactoryProvider factory) {
-        return new TokenBindingManagerAdapter(factory);
-    }
-
-    /**
      * See {@link Context#isDeviceProtectedStorage()}.
      */
     public static boolean isDeviceProtectedStorage(Context context) {
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java
index 4605897..3a9cc34b 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java
@@ -14,7 +14,7 @@
 import org.chromium.android_webview.AwContentsStatics;
 import org.chromium.android_webview.AwDevToolsServer;
 import org.chromium.android_webview.AwSettings;
-import org.chromium.android_webview.command_line.CommandLineUtil;
+import org.chromium.base.BuildInfo;
 import org.chromium.base.Callback;
 import org.chromium.base.MemoryPressureLevel;
 import org.chromium.base.ThreadUtils;
@@ -44,10 +44,9 @@
     }
 
     public void setWebContentsDebuggingEnabled(boolean enable) {
-        // Web Contents debugging is always enabled on debug builds.
-        if (!CommandLineUtil.isBuildDebuggable()) {
-            setWebContentsDebuggingEnabledUnconditionally(enable);
-        }
+        // On debug builds, Web Contents debugging is enabled elsewhere, and cannot be disabled.
+        if (BuildInfo.isDebugAndroid()) return;
+        setWebContentsDebuggingEnabledUnconditionally(enable);
     }
 
     public void setWebContentsDebuggingEnabledUnconditionally(boolean enable) {
@@ -117,23 +116,4 @@
         return ThreadUtils.runOnUiThreadBlockingNoException(
                 () -> AwContentsStatics.getSafeBrowsingPrivacyPolicyUrl());
     }
-
-    public void setProxyOverride(String host, int port, String[] exclusionList, Runnable callback) {
-        if (host == null) {
-            throw new NullPointerException("Host string should not be null");
-        }
-        if (exclusionList != null) {
-            for (String url : exclusionList) {
-                if (url == null) {
-                    throw new NullPointerException("Excluded URL strings should not be null");
-                }
-            }
-        }
-        ThreadUtils.runOnUiThread(
-                () -> AwContentsStatics.setProxyOverride(host, port, exclusionList, callback));
-    }
-
-    public void clearProxyOverride(Runnable callback) {
-        ThreadUtils.runOnUiThread(() -> AwContentsStatics.clearProxyOverride(callback));
-    }
 }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java
index 17fac45..0a7c43e 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java
@@ -25,6 +25,8 @@
     // The WebView wrapper for WebContents and required browser components.
     private AwContents mAwContents;
 
+    private SharedWebViewContentsClientAdapter mContentsClientAdapter;
+
     // Default WebViewClient used to avoid null checks.
     final static WebViewClient sNullWebViewClient = new WebViewClient();
     // The WebViewClient instance that was passed to WebView.setWebViewClient().
@@ -60,7 +62,11 @@
         return mAwContents.getRenderProcess();
     }
 
-    public void setAwContentsOnUiThread(AwContents awContents) {
+    public void init(SharedWebViewContentsClientAdapter contentsClientAdapter) {
+        mContentsClientAdapter = contentsClientAdapter;
+    }
+
+    public void initForReal(AwContents awContents) {
         assert ThreadUtils.runningOnUiThread();
 
         if (mAwContents != null) {
@@ -111,6 +117,34 @@
         mAwContents.postMessageToFrame(null, message, targetOrigin, sentPorts);
     }
 
+    public void setWebViewRendererClientAdapter(
+            SharedWebViewRendererClientAdapter webViewRendererClientAdapter) {
+        if (checkNeedsPost()) {
+            mRunQueue.addTask(new Runnable() {
+                @Override
+                public void run() {
+                    setWebViewRendererClientAdapter(webViewRendererClientAdapter);
+                }
+            });
+            return;
+        }
+        mContentsClientAdapter.setWebViewRendererClientAdapter(webViewRendererClientAdapter);
+    }
+
+    public SharedWebViewRendererClientAdapter getWebViewRendererClientAdapter() {
+        mAwInit.startYourEngines(true);
+        if (checkNeedsPost()) {
+            return mRunQueue.runOnUiThreadBlocking(
+                    new Callable<SharedWebViewRendererClientAdapter>() {
+                        @Override
+                        public SharedWebViewRendererClientAdapter call() {
+                            return getWebViewRendererClientAdapter();
+                        }
+                    });
+        }
+        return mContentsClientAdapter.getWebViewRendererClientAdapter();
+    }
+
     protected boolean checkNeedsPost() {
         boolean needsPost = !mRunQueue.chromiumHasStarted() || !ThreadUtils.runningOnUiThread();
         if (!needsPost && mAwContents == null) {
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java
new file mode 100644
index 0000000..1f2f9b4
--- /dev/null
+++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java
@@ -0,0 +1,245 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package com.android.webview.chromium;
+
+import android.content.Context;
+import android.os.Build;
+import android.support.annotation.Nullable;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import com.android.webview.chromium.WebViewDelegateFactory.WebViewDelegate;
+
+import org.chromium.android_webview.AwContentsClient;
+import org.chromium.android_webview.AwRenderProcess;
+import org.chromium.android_webview.AwSafeBrowsingResponse;
+import org.chromium.android_webview.AwWebResourceResponse;
+import org.chromium.android_webview.SafeBrowsingAction;
+import org.chromium.base.Callback;
+import org.chromium.base.Log;
+import org.chromium.base.TraceEvent;
+import org.chromium.base.compat.ApiHelperForM;
+import org.chromium.base.compat.ApiHelperForN;
+import org.chromium.support_lib_boundary.util.Features;
+import org.chromium.support_lib_callback_glue.SupportLibWebViewContentsClientAdapter;
+
+/**
+ * Partial adapter for AwContentsClient methods that may be handled by either glue layer.
+ */
+abstract class SharedWebViewContentsClientAdapter extends AwContentsClient {
+    // TAG is chosen for consistency with classic webview tracing.
+    protected static final String TAG = "WebViewCallback";
+    // Enables API callback tracing
+    protected static final boolean TRACE = false;
+    // The WebView instance that this adapter is serving.
+    protected final WebView mWebView;
+    // The WebView delegate object that provides access to required framework APIs.
+    protected final WebViewDelegate mWebViewDelegate;
+    // The Context to use. This is different from mWebView.getContext(), which should not be used.
+    protected final Context mContext;
+    // A reference to the current WebViewClient associated with this WebView.
+    protected WebViewClient mWebViewClient = SharedWebViewChromium.sNullWebViewClient;
+    // Some callbacks will be forwarded to this client for apps using the support library.
+    private final SupportLibWebViewContentsClientAdapter mSupportLibClient;
+
+    private @Nullable SharedWebViewRendererClientAdapter mWebViewRendererClientAdapter;
+
+    /**
+     * Adapter constructor.
+     *
+     * @param webView the {@link WebView} instance that this adapter is serving.
+     */
+    SharedWebViewContentsClientAdapter(
+            WebView webView, WebViewDelegate webViewDelegate, Context context) {
+        if (webView == null) {
+            throw new IllegalArgumentException("webView can't be null.");
+        }
+        if (webViewDelegate == null) {
+            throw new IllegalArgumentException("delegate can't be null.");
+        }
+        if (context == null) {
+            throw new IllegalArgumentException("context can't be null.");
+        }
+
+        mWebView = webView;
+        mWebViewDelegate = webViewDelegate;
+        mContext = context;
+        mSupportLibClient = new SupportLibWebViewContentsClientAdapter();
+    }
+
+    void setWebViewClient(WebViewClient client) {
+        mWebViewClient = client;
+        mSupportLibClient.setWebViewClient(client);
+    }
+
+    /**
+     * @see AwContentsClient#hasWebViewClient.
+     */
+    @Override
+    public final boolean hasWebViewClient() {
+        return mWebViewClient != SharedWebViewChromium.sNullWebViewClient;
+    }
+
+    /**
+     * @see AwContentsClient#shouldOverrideUrlLoading(AwContentsClient.AwWebResourceRequest)
+     */
+    @Override
+    public final boolean shouldOverrideUrlLoading(AwContentsClient.AwWebResourceRequest request) {
+        try {
+            TraceEvent.begin("WebViewContentsClientAdapter.shouldOverrideUrlLoading");
+            if (TRACE) Log.i(TAG, "shouldOverrideUrlLoading=" + request.url);
+            boolean result;
+            if (mSupportLibClient.isFeatureAvailable(Features.SHOULD_OVERRIDE_WITH_REDIRECTS)) {
+                result = mSupportLibClient.shouldOverrideUrlLoading(
+                        mWebView, new WebResourceRequestAdapter(request));
+            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                result = ApiHelperForN.shouldOverrideUrlLoading(
+                        mWebViewClient, mWebView, new WebResourceRequestAdapter(request));
+            } else {
+                result = mWebViewClient.shouldOverrideUrlLoading(mWebView, request.url);
+            }
+            if (TRACE) Log.i(TAG, "shouldOverrideUrlLoading result=" + result);
+            return result;
+        } finally {
+            TraceEvent.end("WebViewContentsClientAdapter.shouldOverrideUrlLoading");
+        }
+    }
+
+    /**
+     * @see ContentViewClient#onPageCommitVisible(String)
+     */
+    @Override
+    public final void onPageCommitVisible(String url) {
+        try {
+            TraceEvent.begin("WebViewContentsClientAdapter.onPageCommitVisible");
+            if (TRACE) Log.i(TAG, "onPageCommitVisible=" + url);
+            if (mSupportLibClient.isFeatureAvailable(Features.VISUAL_STATE_CALLBACK)) {
+                mSupportLibClient.onPageCommitVisible(mWebView, url);
+            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                ApiHelperForM.onPageCommitVisible(mWebViewClient, mWebView, url);
+            }
+            // Otherwise, the API does not exist, so do nothing.
+        } finally {
+            TraceEvent.end("WebViewContentsClientAdapter.onPageCommitVisible");
+        }
+    }
+
+    /**
+     * @see ContentViewClient#onReceivedError(int,String,String)
+     */
+    @Override
+    public final void onReceivedError(int errorCode, String description, String failingUrl) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) return;
+
+        // This event is handled by the support lib in {@link #onReceivedError2}.
+        if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_WEB_RESOURCE_ERROR)) return;
+
+        try {
+            TraceEvent.begin("WebViewContentsClientAdapter.onReceivedError");
+            if (description == null || description.isEmpty()) {
+                // ErrorStrings is @hidden, so we can't do this in AwContents.  Normally the net/
+                // layer will set a valid description, but for synthesized callbacks (like in the
+                // case for intercepted requests) AwContents will pass in null.
+                description = mWebViewDelegate.getErrorString(mContext, errorCode);
+            }
+            if (TRACE) Log.i(TAG, "onReceivedError=" + failingUrl);
+            mWebViewClient.onReceivedError(mWebView, errorCode, description, failingUrl);
+        } finally {
+            TraceEvent.end("WebViewContentsClientAdapter.onReceivedError");
+        }
+    }
+
+    /**
+     * @see ContentViewClient#onReceivedError(AwWebResourceRequest,AwWebResourceError)
+     */
+    @Override
+    public void onReceivedError2(AwWebResourceRequest request, AwWebResourceError error) {
+        try {
+            TraceEvent.begin("WebViewContentsClientAdapter.onReceivedError");
+            if (error.description == null || error.description.isEmpty()) {
+                // ErrorStrings is @hidden, so we can't do this in AwContents.  Normally the net/
+                // layer will set a valid description, but for synthesized callbacks (like in the
+                // case for intercepted requests) AwContents will pass in null.
+                error.description = mWebViewDelegate.getErrorString(mContext, error.errorCode);
+            }
+            if (TRACE) Log.i(TAG, "onReceivedError=" + request.url);
+            if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_WEB_RESOURCE_ERROR)) {
+                // Note: we must pass AwWebResourceError, since this class was introduced after L.
+                mSupportLibClient.onReceivedError(
+                        mWebView, new WebResourceRequestAdapter(request), error);
+            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                GlueApiHelperForM.onReceivedError(mWebViewClient, mWebView, request, error);
+            }
+            // Otherwise, this is handled by {@link #onReceivedError}.
+        } finally {
+            TraceEvent.end("WebViewContentsClientAdapter.onReceivedError");
+        }
+    }
+
+    @Override
+    public void onSafeBrowsingHit(AwWebResourceRequest request, int threatType,
+            final Callback<AwSafeBrowsingResponse> callback) {
+        try {
+            TraceEvent.begin("WebViewContentsClientAdapter.onSafeBrowsingHit");
+            if (mSupportLibClient.isFeatureAvailable(Features.SAFE_BROWSING_HIT)) {
+                mSupportLibClient.onSafeBrowsingHit(
+                        mWebView, new WebResourceRequestAdapter(request), threatType, callback);
+            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
+                GlueApiHelperForOMR1.onSafeBrowsingHit(
+                        mWebViewClient, mWebView, request, threatType, callback);
+
+            } else {
+                callback.onResult(new AwSafeBrowsingResponse(SafeBrowsingAction.SHOW_INTERSTITIAL,
+                        /* reporting */ true));
+            }
+        } finally {
+            TraceEvent.end("WebViewContentsClientAdapter.onSafeBrowsingHit");
+        }
+    }
+
+    @Override
+    public void onReceivedHttpError(AwWebResourceRequest request, AwWebResourceResponse response) {
+        try {
+            TraceEvent.begin("WebViewContentsClientAdapter.onReceivedHttpError");
+            if (TRACE) Log.i(TAG, "onReceivedHttpError=" + request.url);
+            if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_HTTP_ERROR)) {
+                // Note: we do not create an immutable instance here, because that constructor is
+                // not available on L.
+                mSupportLibClient.onReceivedHttpError(mWebView,
+                        new WebResourceRequestAdapter(request),
+                        new WebResourceResponse(response.getMimeType(), response.getCharset(),
+                                response.getStatusCode(), response.getReasonPhrase(),
+                                response.getResponseHeaders(), response.getData()));
+            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                GlueApiHelperForM.onReceivedHttpError(mWebViewClient, mWebView, request, response);
+            }
+            // Otherwise, the API does not exist, so do nothing.
+        } finally {
+            TraceEvent.end("WebViewContentsClientAdapter.onReceivedHttpError");
+        }
+    }
+
+    void setWebViewRendererClientAdapter(
+            SharedWebViewRendererClientAdapter webViewRendererClientAdapter) {
+        mWebViewRendererClientAdapter = webViewRendererClientAdapter;
+    }
+
+    SharedWebViewRendererClientAdapter getWebViewRendererClientAdapter() {
+        return mWebViewRendererClientAdapter;
+    }
+
+    @Override
+    public void onRendererUnresponsive(final AwRenderProcess renderProcess) {
+        if (mWebViewRendererClientAdapter != null)
+            mWebViewRendererClientAdapter.onRendererUnresponsive(mWebView, renderProcess);
+    }
+
+    @Override
+    public void onRendererResponsive(final AwRenderProcess renderProcess) {
+        if (mWebViewRendererClientAdapter != null)
+            mWebViewRendererClientAdapter.onRendererResponsive(mWebView, renderProcess);
+    }
+}
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewRendererClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewRendererClientAdapter.java
new file mode 100644
index 0000000..99d78ff
--- /dev/null
+++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewRendererClientAdapter.java
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package com.android.webview.chromium;
+
+import android.webkit.WebView;
+
+import org.chromium.android_webview.AwRenderProcess;
+
+import java.lang.reflect.InvocationHandler;
+
+/**
+ */
+public class SharedWebViewRendererClientAdapter {
+    public SharedWebViewRendererClientAdapter() {}
+
+    public InvocationHandler getSupportLibInvocationHandler() {
+        return null;
+    }
+
+    public void onRendererUnresponsive(final WebView view, final AwRenderProcess renderProcess) {}
+
+    public void onRendererResponsive(final WebView view, final AwRenderProcess renderProcess) {}
+}
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/TokenBindingManagerAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/TokenBindingManagerAdapter.java
deleted file mode 100644
index 7c9060b..0000000
--- a/android_webview/glue/java/src/com/android/webview/chromium/TokenBindingManagerAdapter.java
+++ /dev/null
@@ -1,105 +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 com.android.webview.chromium;
-
-import android.net.Uri;
-import android.webkit.TokenBindingService;
-import android.webkit.TokenBindingService.TokenBindingKey;
-import android.webkit.ValueCallback;
-
-import org.chromium.android_webview.AwTokenBindingManager;
-import org.chromium.base.Callback;
-
-import java.security.KeyPair;
-
-/**
- * Chromium implementation of TokenBindingManager. The API requires
- * all access to TokenBindingManager to be on UI thread, so we start the
- * chromium engines with this assumption.
- */
-public class TokenBindingManagerAdapter extends TokenBindingService {
-
-    private AwTokenBindingManager mTokenBindingManager = new AwTokenBindingManager();
-    private WebViewChromiumFactoryProvider mProvider;
-    private boolean mEnabled;
-
-    TokenBindingManagerAdapter(WebViewChromiumFactoryProvider provider) {
-        mProvider = provider;
-    }
-
-    @Override
-    public void enableTokenBinding() {
-        // We cannot start the chromium engine yet, since doing so would
-        // initialize the UrlRequestContextGetter and then it would be too
-        // late to enable token binding.
-        if (mProvider.hasStarted()) {
-            throw new IllegalStateException(
-                    "Token binding cannot be enabled after webview creation");
-        }
-        mEnabled = true;
-        mTokenBindingManager.enableTokenBinding();
-    }
-
-    @Override
-    public void getKey(Uri origin,
-                       String[] algorithm,
-                       final ValueCallback<TokenBindingKey> callback) {
-        startChromiumEngine();
-        if (algorithm != null && algorithm.length == 0) {
-            throw new IllegalArgumentException("algorithms cannot be empty");
-        }
-        if (algorithm != null) {
-            boolean found = false;
-            for (String alg:algorithm) {
-                if (alg.equals(TokenBindingService.KEY_ALGORITHM_ECDSAP256)) {
-                    found = true; break;
-                }
-            }
-            if (!found) {
-                throw new IllegalArgumentException("no supported algorithm found");
-            }
-        }
-        // Only return the KeyPair for now. We retrieve the key from Channel Id
-        // store which does not provide a way to set/retrieve the Token
-        // Binding algorithms yet.
-        Callback<KeyPair> newCallback = new Callback<KeyPair>() {
-            @Override
-            public void onResult(final KeyPair value) {
-                TokenBindingKey key = new TokenBindingKey() {
-                    @Override
-                    public KeyPair getKeyPair() {
-                        return value;
-                    }
-                    @Override
-                    public String getAlgorithm() {
-                        return TokenBindingService.KEY_ALGORITHM_ECDSAP256;
-                    }
-                };
-                callback.onReceiveValue(key);
-            }
-        };
-        mTokenBindingManager.getKey(origin, null, newCallback);
-    }
-
-    @Override
-    public void deleteKey(Uri origin, final ValueCallback<Boolean> callback) {
-        startChromiumEngine();
-        mTokenBindingManager.deleteKey(origin, CallbackConverter.fromValueCallback(callback));
-    }
-
-    @Override
-    public void deleteAllKeys(final ValueCallback<Boolean> callback) {
-        startChromiumEngine();
-        mTokenBindingManager.deleteAllKeys(CallbackConverter.fromValueCallback(callback));
-    }
-
-    private void startChromiumEngine() {
-        if (!mEnabled) {
-            throw new IllegalStateException("Token binding is not enabled");
-        }
-        // Make sure chromium engine is running.
-        mProvider.startYourEngines(false);
-    }
-}
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 e34c01d..6ca338a 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
@@ -24,6 +24,7 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.print.PrintDocumentAdapter;
+import android.support.annotation.IntDef;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.DragEvent;
@@ -56,12 +57,15 @@
 
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.AwContentsStatics;
+import org.chromium.android_webview.AwDrawFnImpl;
 import org.chromium.android_webview.AwPrintDocumentAdapter;
 import org.chromium.android_webview.AwSettings;
 import org.chromium.android_webview.ResourcesContextWrapperFactory;
 import org.chromium.android_webview.ScopedSysTraceEvent;
 import org.chromium.android_webview.renderer_priority.RendererPriority;
+import org.chromium.base.BuildInfo;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample;
 import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample;
 import org.chromium.components.autofill.AutofillProvider;
 import org.chromium.content_public.browser.NavigationHistory;
@@ -118,6 +122,122 @@
         sRecordWholeDocumentEnabledByApi = true;
     }
 
+    // Used to record the UMA histogram WebView.WebViewApiCall. Since these value are persisted to
+    // logs, they should never be renumbered nor reused.
+    @IntDef({ApiCall.ADD_JAVASCRIPT_INTERFACE, ApiCall.AUTOFILL, ApiCall.CAN_GO_BACK,
+            ApiCall.CAN_GO_BACK_OR_FORWARD, ApiCall.CAN_GO_FORWARD, ApiCall.CAN_ZOOM_IN,
+            ApiCall.CAN_ZOOM_OUT, ApiCall.CAPTURE_PICTURE, ApiCall.CLEAR_CACHE,
+            ApiCall.CLEAR_FORM_DATA, ApiCall.CLEAR_HISTORY, ApiCall.CLEAR_MATCHES,
+            ApiCall.CLEAR_SSL_PREFERENCES, ApiCall.CLEAR_VIEW, ApiCall.COPY_BACK_FORWARD_LIST,
+            ApiCall.CREATE_PRINT_DOCUMENT_ADAPTER, ApiCall.CREATE_WEBMESSAGE_CHANNEL,
+            ApiCall.DOCUMENT_HAS_IMAGES, ApiCall.DOES_SUPPORT_FULLSCREEN,
+            ApiCall.EVALUATE_JAVASCRIPT, ApiCall.EXTRACT_SMART_CLIP_DATA, ApiCall.FIND_NEXT,
+            ApiCall.GET_CERTIFICATE, ApiCall.GET_CONTENT_HEIGHT, ApiCall.GET_CONTENT_WIDTH,
+            ApiCall.GET_FAVICON, ApiCall.GET_HIT_TEST_RESULT,
+            ApiCall.GET_HTTP_AUTH_USERNAME_PASSWORD, ApiCall.GET_ORIGINAL_URL, ApiCall.GET_PROGRESS,
+            ApiCall.GET_SCALE, ApiCall.GET_SETTINGS, ApiCall.GET_TEXT_CLASSIFIER, ApiCall.GET_TITLE,
+            ApiCall.GET_URL, ApiCall.GET_WEBCHROME_CLIENT, ApiCall.GET_WEBVIEW_CLIENT,
+            ApiCall.GO_BACK, ApiCall.GO_BACK_OR_FORWARD, ApiCall.GO_FORWARD,
+            ApiCall.INSERT_VISUAL_STATE_CALLBACK, ApiCall.INVOKE_ZOOM_PICKER, ApiCall.IS_PAUSED,
+            ApiCall.IS_PRIVATE_BROWSING_ENABLED, ApiCall.LOAD_DATA, ApiCall.LOAD_DATA_WITH_BASE_URL,
+            ApiCall.NOTIFY_FIND_DIALOG_DISMISSED, ApiCall.ON_PAUSE,
+            ApiCall.ON_PROVIDE_AUTOFILL_VIRTUAL_STRUCTURE, ApiCall.ON_RESUME,
+            ApiCall.OVERLAY_HORIZONTAL_SCROLLBAR, ApiCall.OVERLAY_VERTICAL_SCROLLBAR,
+            ApiCall.PAGE_DOWN, ApiCall.PAGE_UP, ApiCall.PAUSE_TIMERS,
+            ApiCall.POST_MESSAGE_TO_MAIN_FRAME, ApiCall.POST_URL, ApiCall.RELOAD,
+            ApiCall.REMOVE_JAVASCRIPT_INTERFACE, ApiCall.REQUEST_FOCUS_NODE_HREF,
+            ApiCall.REQUEST_IMAGE_REF, ApiCall.RESTORE_STATE, ApiCall.RESUME_TIMERS,
+            ApiCall.SAVE_STATE, ApiCall.SET_DOWNLOAD_LISTENER, ApiCall.SET_FIND_LISTENER,
+            ApiCall.SET_HORIZONTAL_SCROLLBAR_OVERLAY, ApiCall.SET_HTTP_AUTH_USERNAME_PASSWORD,
+            ApiCall.SET_INITIAL_SCALE, ApiCall.SET_NETWORK_AVAILABLE, ApiCall.SET_PICTURE_LISTENER,
+            ApiCall.SET_SMART_CLIP_RESULT_HANDLER, ApiCall.SET_TEXT_CLASSIFIER,
+            ApiCall.SET_VERTICAL_SCROLLBAR_OVERLAY, ApiCall.SET_WEBCHROME_CLIENT,
+            ApiCall.SET_WEBVIEW_CLIENT, ApiCall.SHOW_FIND_DIALOG, ApiCall.STOP_LOADING})
+    @interface ApiCall {
+        int ADD_JAVASCRIPT_INTERFACE = 0;
+        int AUTOFILL = 1;
+        int CAN_GO_BACK = 2;
+        int CAN_GO_BACK_OR_FORWARD = 3;
+        int CAN_GO_FORWARD = 4;
+        int CAN_ZOOM_IN = 5;
+        int CAN_ZOOM_OUT = 6;
+        int CAPTURE_PICTURE = 7;
+        int CLEAR_CACHE = 8;
+        int CLEAR_FORM_DATA = 9;
+        int CLEAR_HISTORY = 10;
+        int CLEAR_MATCHES = 11;
+        int CLEAR_SSL_PREFERENCES = 12;
+        int CLEAR_VIEW = 13;
+        int COPY_BACK_FORWARD_LIST = 14;
+        int CREATE_PRINT_DOCUMENT_ADAPTER = 15;
+        int CREATE_WEBMESSAGE_CHANNEL = 16;
+        int DOCUMENT_HAS_IMAGES = 17;
+        int DOES_SUPPORT_FULLSCREEN = 18;
+        int EVALUATE_JAVASCRIPT = 19;
+        int EXTRACT_SMART_CLIP_DATA = 20;
+        int FIND_NEXT = 21;
+        int GET_CERTIFICATE = 22;
+        int GET_CONTENT_HEIGHT = 23;
+        int GET_CONTENT_WIDTH = 24;
+        int GET_FAVICON = 25;
+        int GET_HIT_TEST_RESULT = 26;
+        int GET_HTTP_AUTH_USERNAME_PASSWORD = 27;
+        int GET_ORIGINAL_URL = 28;
+        int GET_PROGRESS = 29;
+        int GET_SCALE = 30;
+        int GET_SETTINGS = 31;
+        int GET_TEXT_CLASSIFIER = 32;
+        int GET_TITLE = 33;
+        int GET_URL = 34;
+        int GET_WEBCHROME_CLIENT = 35;
+        int GET_WEBVIEW_CLIENT = 36;
+        int GO_BACK = 37;
+        int GO_BACK_OR_FORWARD = 38;
+        int GO_FORWARD = 39;
+        int INSERT_VISUAL_STATE_CALLBACK = 40;
+        int INVOKE_ZOOM_PICKER = 41;
+        int IS_PAUSED = 42;
+        int IS_PRIVATE_BROWSING_ENABLED = 43;
+        int LOAD_DATA = 44;
+        int LOAD_DATA_WITH_BASE_URL = 45;
+        int NOTIFY_FIND_DIALOG_DISMISSED = 46;
+        int ON_PAUSE = 47;
+        int ON_PROVIDE_AUTOFILL_VIRTUAL_STRUCTURE = 48;
+        int ON_RESUME = 49;
+        int OVERLAY_HORIZONTAL_SCROLLBAR = 50;
+        int OVERLAY_VERTICAL_SCROLLBAR = 51;
+        int PAGE_DOWN = 52;
+        int PAGE_UP = 53;
+        int PAUSE_TIMERS = 54;
+        int POST_MESSAGE_TO_MAIN_FRAME = 55;
+        int POST_URL = 56;
+        int RELOAD = 57;
+        int REMOVE_JAVASCRIPT_INTERFACE = 58;
+        int REQUEST_FOCUS_NODE_HREF = 59;
+        int REQUEST_IMAGE_REF = 60;
+        int RESTORE_STATE = 61;
+        int RESUME_TIMERS = 62;
+        int SAVE_STATE = 63;
+        int SET_DOWNLOAD_LISTENER = 64;
+        int SET_FIND_LISTENER = 65;
+        int SET_HORIZONTAL_SCROLLBAR_OVERLAY = 66;
+        int SET_HTTP_AUTH_USERNAME_PASSWORD = 67;
+        int SET_INITIAL_SCALE = 68;
+        int SET_NETWORK_AVAILABLE = 69;
+        int SET_PICTURE_LISTENER = 70;
+        int SET_SMART_CLIP_RESULT_HANDLER = 71;
+        int SET_TEXT_CLASSIFIER = 72;
+        int SET_VERTICAL_SCROLLBAR_OVERLAY = 73;
+        int SET_WEBCHROME_CLIENT = 74;
+        int SET_WEBVIEW_CLIENT = 75;
+        int SHOW_FIND_DIALOG = 76;
+        int STOP_LOADING = 77;
+        int COUNT = 78;
+    }
+
+    private static final EnumeratedHistogramSample sWebViewApiCallSample =
+            new EnumeratedHistogramSample("WebView.ApiCall", ApiCall.COUNT);
+
     // This does not touch any global / non-threadsafe state, but note that
     // init is ofter called right after and is NOT threadsafe.
     public WebViewChromium(WebViewChromiumFactoryProvider factory, WebView webView,
@@ -198,7 +318,7 @@
                     mFactory.createWebViewContentsClientAdapter(mWebView, mContext);
             try (ScopedSysTraceEvent e2 =
                             ScopedSysTraceEvent.scoped("WebViewChromium.ContentSettingsAdapter")) {
-                mWebSettings = new ContentSettingsAdapter(new AwSettings(mContext,
+                mWebSettings = mFactory.createContentSettingsAdapter(new AwSettings(mContext,
                         isAccessFromFileURLsGrantedByDefault, areLegacyQuirksEnabled,
                         allowEmptyDocumentPersistence, allowGeolocationOnInsecureOrigins,
                         doNotUpdateSelectionOnMutatingSelectionRange));
@@ -218,6 +338,8 @@
 
             if (mShouldDisableThreadChecking) disableThreadChecking();
 
+            mSharedWebViewChromium.init(mContentsClientAdapter);
+
             mFactory.addTask(new Runnable() {
                 @Override
                 public void run() {
@@ -274,8 +396,6 @@
                             return mFactory.createAutofillProvider(context, mWebView);
                         }
                     });
-            mSharedWebViewChromium.setAwContentsOnUiThread(mAwContents);
-
             if (mAppTargetSdkVersion >= Build.VERSION_CODES.KITKAT) {
                 // On KK and above, favicons are automatically downloaded as the method
                 // old apps use to enable that behavior is deprecated.
@@ -290,6 +410,8 @@
 
             // TODO: This assumes AwContents ignores second Paint param.
             mAwContents.setLayerType(mWebView.getLayerType(), null);
+
+            mSharedWebViewChromium.initForReal(mAwContents);
         }
     }
 
@@ -327,6 +449,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.SET_HORIZONTAL_SCROLLBAR_OVERLAY);
         mAwContents.setHorizontalScrollbarOverlay(overlay);
     }
 
@@ -341,6 +464,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.SET_VERTICAL_SCROLLBAR_OVERLAY);
         mAwContents.setVerticalScrollbarOverlay(overlay);
     }
 
@@ -356,6 +480,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.OVERLAY_HORIZONTAL_SCROLLBAR);
         return mAwContents.overlayHorizontalScrollbar();
     }
 
@@ -371,6 +496,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.OVERLAY_VERTICAL_SCROLLBAR);
         return mAwContents.overlayVerticalScrollbar();
     }
 
@@ -392,6 +518,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.GET_CERTIFICATE);
         return mAwContents.getCertificate();
     }
 
@@ -417,6 +544,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.SET_HTTP_AUTH_USERNAME_PASSWORD);
         ((WebViewDatabaseAdapter) mFactory.getWebViewDatabase(mContext))
                 .setHttpAuthUsernamePassword(host, realm, username, password);
     }
@@ -433,6 +561,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.GET_HTTP_AUTH_USERNAME_PASSWORD);
         return ((WebViewDatabaseAdapter) mFactory.getWebViewDatabase(mContext))
                 .getHttpAuthUsernamePassword(host, realm);
     }
@@ -472,6 +601,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.SET_NETWORK_AVAILABLE);
         mAwContents.setNetworkAvailable(networkUp);
     }
 
@@ -488,6 +618,7 @@
                     });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.SAVE_STATE);
         if (outState == null) return null;
         if (!mAwContents.saveState(outState)) return null;
         return copyBackForwardList();
@@ -518,6 +649,7 @@
                     });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.RESTORE_STATE);
         if (inState == null) return null;
         if (!mAwContents.restoreState(inState)) return null;
         return copyBackForwardList();
@@ -566,11 +698,13 @@
             mFactory.addTask(new Runnable() {
                 @Override
                 public void run() {
+                    sWebViewApiCallSample.record(ApiCall.POST_URL);
                     mAwContents.postUrl(url, postData);
                 }
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.POST_URL);
         mAwContents.postUrl(url, postData);
     }
 
@@ -583,11 +717,13 @@
             mFactory.addTask(new Runnable() {
                 @Override
                 public void run() {
+                    sWebViewApiCallSample.record(ApiCall.LOAD_DATA);
                     mAwContents.loadData(data, mimeType, encoding);
                 }
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.LOAD_DATA);
         mAwContents.loadData(data, mimeType, encoding);
     }
 
@@ -601,11 +737,13 @@
             mFactory.addTask(new Runnable() {
                 @Override
                 public void run() {
+                    sWebViewApiCallSample.record(ApiCall.LOAD_DATA_WITH_BASE_URL);
                     mAwContents.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
                 }
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.LOAD_DATA_WITH_BASE_URL);
         mAwContents.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
     }
 
@@ -617,11 +755,13 @@
             mFactory.addTask(new Runnable() {
                 @Override
                 public void run() {
+                    sWebViewApiCallSample.record(ApiCall.EVALUATE_JAVASCRIPT);
                     mAwContents.evaluateJavaScript(
                             script, CallbackConverter.fromValueCallback(resultCallback));
                 }
             });
         } else {
+            sWebViewApiCallSample.record(ApiCall.EVALUATE_JAVASCRIPT);
             checkThread();
             mAwContents.evaluateJavaScript(
                     script, CallbackConverter.fromValueCallback(resultCallback));
@@ -661,6 +801,7 @@
             return;
         }
 
+        sWebViewApiCallSample.record(ApiCall.STOP_LOADING);
         mAwContents.stopLoading();
     }
 
@@ -675,6 +816,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.RELOAD);
         mAwContents.reload();
     }
 
@@ -690,6 +832,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.CAN_GO_BACK);
         return mAwContents.canGoBack();
     }
 
@@ -704,6 +847,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.GO_BACK);
         mAwContents.goBack();
     }
 
@@ -719,6 +863,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.CAN_GO_FORWARD);
         return mAwContents.canGoForward();
     }
 
@@ -733,6 +878,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.GO_FORWARD);
         mAwContents.goForward();
     }
 
@@ -748,6 +894,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.CAN_GO_BACK_OR_FORWARD);
         return mAwContents.canGoBackOrForward(steps);
     }
 
@@ -762,12 +909,14 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.GO_BACK_OR_FORWARD);
         mAwContents.goBackOrForward(steps);
     }
 
     @Override
     public boolean isPrivateBrowsingEnabled() {
         // Not supported in this WebView implementation.
+        sWebViewApiCallSample.record(ApiCall.IS_PRIVATE_BROWSING_ENABLED);
         return false;
     }
 
@@ -783,6 +932,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.PAGE_UP);
         return mAwContents.pageUp(top);
     }
 
@@ -798,6 +948,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.PAGE_DOWN);
         return mAwContents.pageDown(bottom);
     }
 
@@ -805,6 +956,7 @@
     @TargetApi(Build.VERSION_CODES.M)
     public void insertVisualStateCallback(
             final long requestId, final VisualStateCallback callback) {
+        sWebViewApiCallSample.record(ApiCall.INSERT_VISUAL_STATE_CALLBACK);
         mSharedWebViewChromium.insertVisualStateCallback(
                 requestId, new AwContents.VisualStateCallback() {
                     @Override
@@ -825,6 +977,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.CLEAR_VIEW);
         mAwContents.clearView();
     }
 
@@ -840,11 +993,13 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.CAPTURE_PICTURE);
         return mAwContents.capturePicture();
     }
 
     @Override
     public float getScale() {
+        sWebViewApiCallSample.record(ApiCall.GET_SCALE);
         // No checkThread() as it is mostly thread safe (workaround for b/10652991).
         mFactory.startYourEngines(true);
         return mAwContents.getScale();
@@ -852,6 +1007,7 @@
 
     @Override
     public void setInitialScale(final int scaleInPercent) {
+        sWebViewApiCallSample.record(ApiCall.SET_INITIAL_SCALE);
         // No checkThread() as it is thread safe
         mWebSettings.getAwSettings().setInitialPageScale(scaleInPercent);
     }
@@ -867,6 +1023,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.INVOKE_ZOOM_PICKER);
         mAwContents.invokeZoomPicker();
     }
 
@@ -883,6 +1040,7 @@
                     });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.GET_HIT_TEST_RESULT);
         AwContents.HitTestData data = mAwContents.getLastHitTestResult();
         mHitTestResult.setType(data.hitTestResultType);
         mHitTestResult.setExtra(data.hitTestResultExtraData);
@@ -900,6 +1058,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.REQUEST_FOCUS_NODE_HREF);
         mAwContents.requestFocusNodeHref(hrefMsg);
     }
 
@@ -914,6 +1073,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.REQUEST_IMAGE_REF);
         mAwContents.requestImageRef(msg);
     }
 
@@ -929,6 +1089,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.GET_URL);
         return mAwContents.getUrl();
     }
 
@@ -944,6 +1105,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.GET_ORIGINAL_URL);
         return mAwContents.getOriginalUrl();
     }
 
@@ -959,6 +1121,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.GET_TITLE);
         return mAwContents.getTitle();
     }
 
@@ -974,6 +1137,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.GET_FAVICON);
         return mAwContents.getFavicon();
     }
 
@@ -985,6 +1149,7 @@
 
     @Override
     public int getProgress() {
+        sWebViewApiCallSample.record(ApiCall.GET_PROGRESS);
         if (mAwContents == null) return 100;
         // No checkThread() because the value is cached java side (workaround for b/10533304).
         return mAwContents.getMostRecentProgress();
@@ -992,6 +1157,7 @@
 
     @Override
     public int getContentHeight() {
+        sWebViewApiCallSample.record(ApiCall.GET_CONTENT_HEIGHT);
         if (mAwContents == null) return 0;
         // No checkThread() as it is mostly thread safe (workaround for b/10594869).
         return mAwContents.getContentHeightCss();
@@ -999,6 +1165,7 @@
 
     @Override
     public int getContentWidth() {
+        sWebViewApiCallSample.record(ApiCall.GET_CONTENT_WIDTH);
         if (mAwContents == null) return 0;
         // No checkThread() as it is mostly thread safe (workaround for b/10594869).
         return mAwContents.getContentWidthCss();
@@ -1015,6 +1182,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.PAUSE_TIMERS);
         mAwContents.pauseTimers();
     }
 
@@ -1029,6 +1197,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.RESUME_TIMERS);
         mAwContents.resumeTimers();
     }
 
@@ -1043,6 +1212,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.ON_PAUSE);
         mAwContents.onPause();
     }
 
@@ -1057,6 +1227,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.ON_RESUME);
         mAwContents.onResume();
     }
 
@@ -1072,6 +1243,7 @@
             });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.IS_PAUSED);
         return mAwContents.isPaused();
     }
 
@@ -1091,6 +1263,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.CLEAR_CACHE);
         mAwContents.clearCache(includeDiskFiles);
     }
 
@@ -1108,6 +1281,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.CLEAR_FORM_DATA);
         mAwContents.hideAutofillPopup();
     }
 
@@ -1122,6 +1296,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.CLEAR_HISTORY);
         mAwContents.clearHistory();
     }
 
@@ -1136,6 +1311,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.CLEAR_SSL_PREFERENCES);
         mAwContents.clearSslPreferences();
     }
 
@@ -1152,6 +1328,7 @@
                     });
             return ret;
         }
+        sWebViewApiCallSample.record(ApiCall.COPY_BACK_FORWARD_LIST);
         // mAwContents.getNavigationHistory() can be null here if mAwContents has been destroyed,
         // and we do not handle passing null to the WebBackForwardListChromium constructor.
         NavigationHistory navHistory = mAwContents.getNavigationHistory();
@@ -1161,6 +1338,7 @@
 
     @Override
     public void setFindListener(WebView.FindListener listener) {
+        sWebViewApiCallSample.record(ApiCall.SET_FIND_LISTENER);
         mContentsClientAdapter.setFindListener(listener);
     }
 
@@ -1175,6 +1353,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.FIND_NEXT);
         mAwContents.findNext(forwards);
     }
 
@@ -1200,6 +1379,7 @@
 
     @Override
     public boolean showFindDialog(final String text, final boolean showIme) {
+        sWebViewApiCallSample.record(ApiCall.SHOW_FIND_DIALOG);
         mFactory.startYourEngines(false);
         if (checkNeedsPost()) {
             return false;
@@ -1238,6 +1418,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.NOTIFY_FIND_DIALOG_DISMISSED);
         clearMatches();
     }
 
@@ -1252,6 +1433,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.CLEAR_MATCHES);
         mAwContents.clearMatches();
     }
 
@@ -1266,27 +1448,32 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.DOCUMENT_HAS_IMAGES);
         mAwContents.documentHasImages(response);
     }
 
     @Override
     public void setWebViewClient(WebViewClient client) {
+        sWebViewApiCallSample.record(ApiCall.SET_WEBVIEW_CLIENT);
         mSharedWebViewChromium.setWebViewClient(client);
         mContentsClientAdapter.setWebViewClient(mSharedWebViewChromium.getWebViewClient());
     }
 
     @Override
     public WebViewClient getWebViewClient() {
+        sWebViewApiCallSample.record(ApiCall.GET_WEBVIEW_CLIENT);
         return mSharedWebViewChromium.getWebViewClient();
     }
 
     @Override
     public void setDownloadListener(DownloadListener listener) {
+        sWebViewApiCallSample.record(ApiCall.SET_DOWNLOAD_LISTENER);
         mContentsClientAdapter.setDownloadListener(listener);
     }
 
     @Override
     public void setWebChromeClient(WebChromeClient client) {
+        sWebViewApiCallSample.record(ApiCall.SET_WEBCHROME_CLIENT);
         mWebSettings.getAwSettings().setFullscreenSupported(doesSupportFullscreen(client));
         mSharedWebViewChromium.setWebChromeClient(client);
         mContentsClientAdapter.setWebChromeClient(mSharedWebViewChromium.getWebChromeClient());
@@ -1294,6 +1481,7 @@
 
     @Override
     public WebChromeClient getWebChromeClient() {
+        sWebViewApiCallSample.record(ApiCall.GET_WEBCHROME_CLIENT);
         return mSharedWebViewChromium.getWebChromeClient();
     }
 
@@ -1304,6 +1492,7 @@
      * and {@link WebChromeClient#onHideCustomView()} are required.
      */
     private boolean doesSupportFullscreen(WebChromeClient client) {
+        sWebViewApiCallSample.record(ApiCall.DOES_SUPPORT_FULLSCREEN);
         if (client == null) {
             return false;
         }
@@ -1346,6 +1535,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.SET_PICTURE_LISTENER);
         boolean invalidateOnly = mAppTargetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR2;
         mContentsClientAdapter.setPictureListener(listener, invalidateOnly);
         mAwContents.enableOnNewPicture(listener != null, invalidateOnly);
@@ -1362,6 +1552,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.ADD_JAVASCRIPT_INTERFACE);
         mAwContents.addJavascriptInterface(obj, interfaceName);
     }
 
@@ -1376,11 +1567,13 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.REMOVE_JAVASCRIPT_INTERFACE);
         mAwContents.removeJavascriptInterface(interfaceName);
     }
 
     @Override
     public WebMessagePort[] createWebMessageChannel() {
+        sWebViewApiCallSample.record(ApiCall.CREATE_WEBMESSAGE_CHANNEL);
         return WebMessagePortAdapter.fromMessagePorts(
                 mSharedWebViewChromium.createWebMessageChannel());
     }
@@ -1388,12 +1581,14 @@
     @Override
     @TargetApi(Build.VERSION_CODES.M)
     public void postMessageToMainFrame(final WebMessage message, final Uri targetOrigin) {
+        sWebViewApiCallSample.record(ApiCall.POST_MESSAGE_TO_MAIN_FRAME);
         mSharedWebViewChromium.postMessageToMainFrame(message.getData(), targetOrigin.toString(),
                 WebMessagePortAdapter.toMessagePorts(message.getPorts()));
     }
 
     @Override
     public WebSettings getSettings() {
+        sWebViewApiCallSample.record(ApiCall.GET_SETTINGS);
         return mWebSettings;
     }
 
@@ -1431,6 +1626,7 @@
 
     @Override
     public boolean canZoomIn() {
+        sWebViewApiCallSample.record(ApiCall.CAN_ZOOM_IN);
         if (checkNeedsPost()) {
             return false;
         }
@@ -1439,6 +1635,7 @@
 
     @Override
     public boolean canZoomOut() {
+        sWebViewApiCallSample.record(ApiCall.CAN_ZOOM_OUT);
         if (checkNeedsPost()) {
             return false;
         }
@@ -1539,11 +1736,13 @@
 
     @Override
     public void setTextClassifier(TextClassifier textClassifier) {
+        sWebViewApiCallSample.record(ApiCall.SET_TEXT_CLASSIFIER);
         mAwContents.setTextClassifier(textClassifier);
     }
 
     @Override
     public TextClassifier getTextClassifier() {
+        sWebViewApiCallSample.record(ApiCall.GET_TEXT_CLASSIFIER);
         return mAwContents.getTextClassifier();
     }
 
@@ -1558,6 +1757,7 @@
                 }
             });
         }
+        sWebViewApiCallSample.record(ApiCall.AUTOFILL);
         mAwContents.autofill(values);
     }
 
@@ -1573,6 +1773,7 @@
             });
             return;
         }
+        sWebViewApiCallSample.record(ApiCall.ON_PROVIDE_AUTOFILL_VIRTUAL_STRUCTURE);
         mAwContents.onProvideAutoFillVirtualStructure(structure, flags);
     }
 
@@ -2272,6 +2473,7 @@
 
     @Override
     public PrintDocumentAdapter createPrintDocumentAdapter(String documentName) {
+        sWebViewApiCallSample.record(ApiCall.CREATE_PRINT_DOCUMENT_ADAPTER);
         checkThread();
         return new AwPrintDocumentAdapter(mAwContents.getPdfExporter(), documentName);
     }
@@ -2281,6 +2483,14 @@
         public AwContents.NativeDrawGLFunctor createGLFunctor(long context) {
             return new DrawGLFunctor(context, mFactory.getWebViewDelegate());
         }
+
+        @Override
+        public AwDrawFnImpl.DrawFnAccess getDrawFnAccess() {
+            if (BuildInfo.isAtLeastQ()) {
+                return mFactory.getWebViewDelegate();
+            }
+            return null;
+        }
     }
 
     // AwContents.InternalAccessDelegate implementation --------------------------------------
@@ -2360,6 +2570,7 @@
     // Implements SmartClipProvider
     @Override
     public void extractSmartClipData(int x, int y, int width, int height) {
+        sWebViewApiCallSample.record(ApiCall.EXTRACT_SMART_CLIP_DATA);
         checkThread();
         mAwContents.extractSmartClipData(x, y, width, height);
     }
@@ -2367,6 +2578,7 @@
     // Implements SmartClipProvider
     @Override
     public void setSmartClipResultHandler(final Handler resultHandler) {
+        sWebViewApiCallSample.record(ApiCall.SET_SMART_CLIP_RESULT_HANDLER);
         checkThread();
         mAwContents.setSmartClipResultHandler(resultHandler);
     }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
index 95c649e..a873c92 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
@@ -5,7 +5,6 @@
 package com.android.webview.chromium;
 
 import android.Manifest;
-import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -15,7 +14,6 @@
 import android.util.Log;
 import android.webkit.CookieManager;
 import android.webkit.GeolocationPermissions;
-import android.webkit.TokenBindingService;
 import android.webkit.WebStorage;
 import android.webkit.WebViewDatabase;
 
@@ -26,7 +24,9 @@
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.AwContentsStatics;
 import org.chromium.android_webview.AwCookieManager;
+import org.chromium.android_webview.AwDrawFnImpl;
 import org.chromium.android_webview.AwNetworkChangeNotifierRegistrationPolicy;
+import org.chromium.android_webview.AwProxyController;
 import org.chromium.android_webview.AwQuotaManagerBridge;
 import org.chromium.android_webview.AwResource;
 import org.chromium.android_webview.AwServiceWorkerController;
@@ -35,14 +35,13 @@
 import org.chromium.android_webview.ScopedSysTraceEvent;
 import org.chromium.android_webview.VariationsSeedLoader;
 import org.chromium.android_webview.WebViewChromiumRunQueue;
-import org.chromium.android_webview.command_line.CommandLineUtil;
 import org.chromium.base.BuildConfig;
+import org.chromium.base.BuildInfo;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.FieldTrialList;
 import org.chromium.base.PathService;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.TraceEvent;
-import org.chromium.base.annotations.DoNotInline;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.base.library_loader.ProcessInitException;
@@ -61,16 +60,6 @@
 
     private static final String HTTP_AUTH_DATABASE_FILE = "http_auth.db";
 
-    /**
-     * This holds objects of classes that are defined in N and above to ensure that run-time class
-     * verification does not occur until it is actually used for N and above.
-     */
-    @TargetApi(Build.VERSION_CODES.N)
-    @DoNotInline
-    private static class ObjectHolderForN {
-        public TokenBindingService mTokenBindingService;
-    }
-
     // TODO(gsennton): store aw-objects instead of adapters here
     // Initialization guarded by mLock.
     private AwBrowserContext mBrowserContext;
@@ -78,10 +67,6 @@
     private GeolocationPermissionsAdapter mGeolocationPermissions;
     private CookieManagerAdapter mCookieManager;
 
-    @TargetApi(Build.VERSION_CODES.N)
-    private ObjectHolderForN mObjectHolderForN =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new ObjectHolderForN() : null;
-
     private WebIconDatabaseAdapter mWebIconDatabase;
     private WebStorageAdapter mWebStorage;
     private WebViewDatabaseAdapter mWebViewDatabase;
@@ -89,6 +74,7 @@
     private AwTracingController mAwTracingController;
     private VariationsSeedLoader mSeedLoader;
     private Thread mSetUpResourcesThread;
+    private AwProxyController mAwProxyController;
 
     // Guards accees to the other members, and is notifyAll() signalled on the UI thread
     // when the chromium process has been started.
@@ -116,6 +102,15 @@
         return mAwTracingController;
     }
 
+    public AwProxyController getAwProxyController() {
+        synchronized (mLock) {
+            if (mAwProxyController == null) {
+                ensureChromiumStartedLocked(true);
+            }
+        }
+        return mAwProxyController;
+    }
+
     // TODO: DIR_RESOURCE_PAKS_ANDROID needs to live somewhere sensible,
     // inlined here for simplicity setting up the HTMLViewer demo. Unfortunately
     // it can't go into base.PathService, as the native constant it refers to
@@ -167,7 +162,7 @@
             AwBrowserProcess.handleMinidumpsAndSetMetricsConsent(true /* updateMetricsConsent */);
 
             mSharedStatics = new SharedStatics();
-            if (CommandLineUtil.isBuildDebuggable()) {
+            if (BuildInfo.isDebugAndroid()) {
                 mSharedStatics.setWebContentsDebuggingEnabledUnconditionally(true);
             }
 
@@ -198,6 +193,7 @@
                 mWebStorage = new WebStorageAdapter(mFactory, AwQuotaManagerBridge.getInstance());
                 mAwTracingController = awBrowserContext.getTracingController();
                 mServiceWorkerController = awBrowserContext.getServiceWorkerController();
+                mAwProxyController = new AwProxyController();
             }
 
             mFactory.getRunQueue().drainQueue();
@@ -305,6 +301,9 @@
     private void initPlatSupportLibrary() {
         try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped(
                      "WebViewChromiumAwInit.initPlatSupportLibrary")) {
+            if (BuildInfo.isAtLeastQ()) {
+                AwDrawFnImpl.setDrawFnFunctionTable(DrawFunctor.getDrawFnFunctionTable());
+            }
             DrawGLFunctor.setChromiumAwDrawGLFunction(AwContents.getAwDrawGLFunction());
             AwContents.setAwDrawSWFunctionTable(GraphicsUtils.getDrawSWFunctionTable());
             AwContents.setAwDrawGLFunctionTable(GraphicsUtils.getDrawGLFunctionTable());
@@ -392,17 +391,6 @@
         return mServiceWorkerController;
     }
 
-    @TargetApi(Build.VERSION_CODES.N)
-    public TokenBindingService getTokenBindingService() {
-        synchronized (mLock) {
-            if (mObjectHolderForN.mTokenBindingService == null) {
-                mObjectHolderForN.mTokenBindingService =
-                        GlueApiHelperForN.createTokenBindingManagerAdapter(mFactory);
-            }
-        }
-        return mObjectHolderForN.mTokenBindingService;
-    }
-
     public android.webkit.WebIconDatabase getWebIconDatabase() {
         synchronized (mLock) {
             ensureChromiumStartedLocked(true);
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
index 3016955..b9d67ea 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -32,6 +32,7 @@
 import org.chromium.android_webview.AwAutofillProvider;
 import org.chromium.android_webview.AwBrowserContext;
 import org.chromium.android_webview.AwBrowserProcess;
+import org.chromium.android_webview.AwSettings;
 import org.chromium.android_webview.ResourcesContextWrapperFactory;
 import org.chromium.android_webview.ScopedSysTraceEvent;
 import org.chromium.android_webview.WebViewChromiumRunQueue;
@@ -200,6 +201,11 @@
         }
     }
 
+    // Protected to allow downstream to override.
+    protected ContentSettingsAdapter createContentSettingsAdapter(AwSettings settings) {
+        return new ContentSettingsAdapter(settings);
+    }
+
     private void deleteContentsOnPackageDowngrade(PackageInfo packageInfo) {
         try (ScopedSysTraceEvent e2 = ScopedSysTraceEvent.scoped(
                      "WebViewChromiumFactoryProvider.deleteContentsOnPackageDowngrade")) {
@@ -522,7 +528,7 @@
 
     @Override
     public TokenBindingService getTokenBindingService() {
-        return mAwInit.getTokenBindingService();
+        return null;
     }
 
     @Override
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
index aa04e28..7cb2889 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -4,7 +4,6 @@
 
 package com.android.webview.chromium;
 
-import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -43,13 +42,10 @@
 import org.chromium.android_webview.AwContentsClientBridge;
 import org.chromium.android_webview.AwGeolocationPermissions;
 import org.chromium.android_webview.AwHttpAuthHandler;
-import org.chromium.android_webview.AwRenderProcess;
 import org.chromium.android_webview.AwRenderProcessGoneDetail;
-import org.chromium.android_webview.AwSafeBrowsingResponse;
 import org.chromium.android_webview.AwWebResourceResponse;
 import org.chromium.android_webview.JsPromptResultReceiver;
 import org.chromium.android_webview.JsResultReceiver;
-import org.chromium.android_webview.SafeBrowsingAction;
 import org.chromium.android_webview.ScopedSysTraceEvent;
 import org.chromium.android_webview.permission.AwPermissionRequest;
 import org.chromium.android_webview.permission.Resource;
@@ -57,10 +53,6 @@
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.TraceEvent;
-import org.chromium.base.compat.ApiHelperForM;
-import org.chromium.base.compat.ApiHelperForN;
-import org.chromium.support_lib_boundary.util.Features;
-import org.chromium.support_lib_callback_glue.SupportLibWebViewContentsClientAdapter;
 
 import java.lang.ref.WeakReference;
 import java.security.Principal;
@@ -88,20 +80,7 @@
  * allow the source WebView to be injected by ContentViewClientAdapter. We
  * choose the latter, because it makes for a cleaner design.
  */
-@SuppressWarnings("deprecation")
-class WebViewContentsClientAdapter extends AwContentsClient {
-    // TAG is chosen for consistency with classic webview tracing.
-    private static final String TAG = "WebViewCallback";
-    // Enables API callback tracing
-    private static final boolean TRACE = false;
-    // The WebView instance that this adapter is serving.
-    protected final WebView mWebView;
-    // The Context to use. This is different from mWebView.getContext(), which should not be used.
-    private final Context mContext;
-    // A reference to the current WebViewClient associated with this WebView.
-    protected WebViewClient mWebViewClient = SharedWebViewChromium.sNullWebViewClient;
-    // Some callbacks will be forwarded to this client for apps using the support library.
-    private final SupportLibWebViewContentsClientAdapter mSupportLibClient;
+class WebViewContentsClientAdapter extends SharedWebViewContentsClientAdapter {
     // The WebChromeClient instance that was passed to WebView.setContentViewClient().
     private WebChromeClient mWebChromeClient;
     // The listener receiving find-in-page API results.
@@ -111,8 +90,6 @@
     // Whether the picture listener is invalidate only (i.e. receives a null Picture)
     private boolean mPictureListenerInvalidateOnly;
 
-    private WebViewDelegate mWebViewDelegate;
-
     private DownloadListener mDownloadListener;
 
     private Handler mUiThreadHandler;
@@ -127,24 +104,11 @@
      *
      * @param webView the {@link WebView} instance that this adapter is serving.
      */
-    @SuppressLint("HandlerLeak")
     WebViewContentsClientAdapter(WebView webView, Context context,
             WebViewDelegate webViewDelegate) {
-        if (webView == null || webViewDelegate == null) {
-            throw new IllegalArgumentException("webView or delegate can't be null.");
-        }
-
-        if (context == null) {
-            throw new IllegalArgumentException("context can't be null.");
-        }
-
-        mContext = context;
-        mWebView = webView;
-        mWebViewDelegate = webViewDelegate;
+        super(webView, webViewDelegate, context);
         try (ScopedSysTraceEvent event =
                         ScopedSysTraceEvent.scoped("WebViewContentsClientAdapter.constructor")) {
-            mSupportLibClient = new SupportLibWebViewContentsClientAdapter();
-
             mUiThreadHandler = new Handler() {
                 @Override
                 public void handleMessage(Message msg) {
@@ -175,11 +139,6 @@
         }
     }
 
-    void setWebViewClient(WebViewClient client) {
-        mWebViewClient = client;
-        mSupportLibClient.setWebViewClient(client);
-    }
-
     void setWebChromeClient(WebChromeClient client) {
         mWebChromeClient = client;
     }
@@ -206,14 +165,6 @@
     //--------------------------------------------------------------------------------------------
 
     /**
-     * @see AwContentsClient#hasWebViewClient.
-     */
-    @Override
-    public boolean hasWebViewClient() {
-        return mWebViewClient != SharedWebViewChromium.sNullWebViewClient;
-    }
-
-    /**
      * @see AwContentsClient#getVisitedHistory.
      */
     @Override
@@ -289,31 +240,6 @@
     }
 
     /**
-     * @see AwContentsClient#shouldOverrideUrlLoading(AwContentsClient.AwWebResourceRequest)
-     */
-    @Override
-    public boolean shouldOverrideUrlLoading(AwContentsClient.AwWebResourceRequest request) {
-        try {
-            TraceEvent.begin("WebViewContentsClientAdapter.shouldOverrideUrlLoading");
-            if (TRACE) Log.i(TAG, "shouldOverrideUrlLoading=" + request.url);
-            boolean result;
-            if (mSupportLibClient.isFeatureAvailable(Features.SHOULD_OVERRIDE_WITH_REDIRECTS)) {
-                result = mSupportLibClient.shouldOverrideUrlLoading(
-                        mWebView, new WebResourceRequestAdapter(request));
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                result = ApiHelperForN.shouldOverrideUrlLoading(
-                        mWebViewClient, mWebView, new WebResourceRequestAdapter(request));
-            } else {
-                result = mWebViewClient.shouldOverrideUrlLoading(mWebView, request.url);
-            }
-            if (TRACE) Log.i(TAG, "shouldOverrideUrlLoading result=" + result);
-            return result;
-        } finally {
-            TraceEvent.end("WebViewContentsClientAdapter.shouldOverrideUrlLoading");
-        }
-    }
-
-    /**
      * @see AwContentsClient#onUnhandledKeyEvent(android.view.KeyEvent)
      */
     @Override
@@ -524,121 +450,6 @@
     }
 
     /**
-     * @see ContentViewClient#onPageCommitVisible(String)
-     */
-    @Override
-    public void onPageCommitVisible(String url) {
-        try {
-            TraceEvent.begin("WebViewContentsClientAdapter.onPageCommitVisible");
-            if (TRACE) Log.i(TAG, "onPageCommitVisible=" + url);
-            if (mSupportLibClient.isFeatureAvailable(Features.VISUAL_STATE_CALLBACK)) {
-                mSupportLibClient.onPageCommitVisible(mWebView, url);
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                ApiHelperForM.onPageCommitVisible(mWebViewClient, mWebView, url);
-            }
-            // Otherwise, the API does not exist, so do nothing.
-        } finally {
-            TraceEvent.end("WebViewContentsClientAdapter.onPageCommitVisible");
-        }
-    }
-
-    /**
-     * @see ContentViewClient#onReceivedError(int,String,String)
-     */
-    @Override
-    public void onReceivedError(int errorCode, String description, String failingUrl) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) return;
-
-        // This event is handled by the support lib in {@link #onReceivedError2}.
-        if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_WEB_RESOURCE_ERROR)) return;
-
-        try {
-            TraceEvent.begin("WebViewContentsClientAdapter.onReceivedError");
-            if (description == null || description.isEmpty()) {
-                // ErrorStrings is @hidden, so we can't do this in AwContents.  Normally the net/
-                // layer will set a valid description, but for synthesized callbacks (like in the
-                // case for intercepted requests) AwContents will pass in null.
-                description = mWebViewDelegate.getErrorString(mContext, errorCode);
-            }
-            if (TRACE) Log.i(TAG, "onReceivedError=" + failingUrl);
-            mWebViewClient.onReceivedError(
-                    mWebView, errorCode, description, failingUrl);
-        } finally {
-            TraceEvent.end("WebViewContentsClientAdapter.onReceivedError");
-        }
-    }
-
-    /**
-     * @see ContentViewClient#onReceivedError(AwWebResourceRequest,AwWebResourceError)
-     */
-    @Override
-    public void onReceivedError2(AwWebResourceRequest request, AwWebResourceError error) {
-        try {
-            TraceEvent.begin("WebViewContentsClientAdapter.onReceivedError");
-            if (error.description == null || error.description.isEmpty()) {
-                // ErrorStrings is @hidden, so we can't do this in AwContents.  Normally the net/
-                // layer will set a valid description, but for synthesized callbacks (like in the
-                // case for intercepted requests) AwContents will pass in null.
-                error.description = mWebViewDelegate.getErrorString(mContext, error.errorCode);
-            }
-            if (TRACE) Log.i(TAG, "onReceivedError=" + request.url);
-            if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_WEB_RESOURCE_ERROR)) {
-                // Note: we must pass AwWebResourceError, since this class was introduced after L.
-                mSupportLibClient.onReceivedError(
-                        mWebView, new WebResourceRequestAdapter(request), error);
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                GlueApiHelperForM.onReceivedError(mWebViewClient, mWebView, request, error);
-            }
-            // Otherwise, this is handled by {@link #onReceivedError}.
-        } finally {
-            TraceEvent.end("WebViewContentsClientAdapter.onReceivedError");
-        }
-    }
-
-    @Override
-    public void onSafeBrowsingHit(AwWebResourceRequest request, int threatType,
-            final Callback<AwSafeBrowsingResponse> callback) {
-        try {
-            TraceEvent.begin("WebViewContentsClientAdapter.onSafeBrowsingHit");
-            if (mSupportLibClient.isFeatureAvailable(Features.SAFE_BROWSING_HIT)) {
-                mSupportLibClient.onSafeBrowsingHit(
-                        mWebView, new WebResourceRequestAdapter(request), threatType, callback);
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
-                GlueApiHelperForOMR1.onSafeBrowsingHit(
-                        mWebViewClient, mWebView, request, threatType, callback);
-
-            } else {
-                callback.onResult(new AwSafeBrowsingResponse(SafeBrowsingAction.SHOW_INTERSTITIAL,
-                        /* reporting */ true));
-            }
-        } finally {
-            TraceEvent.end("WebViewContentsClientAdapter.onSafeBrowsingHit");
-        }
-    }
-
-    @Override
-    public void onReceivedHttpError(AwWebResourceRequest request, AwWebResourceResponse response) {
-        try {
-            TraceEvent.begin("WebViewContentsClientAdapter.onReceivedHttpError");
-            if (TRACE) Log.i(TAG, "onReceivedHttpError=" + request.url);
-            if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_HTTP_ERROR)) {
-                // Note: we do not create an immutable instance here, because that constructor is
-                // not available on L.
-                mSupportLibClient.onReceivedHttpError(mWebView,
-                        new WebResourceRequestAdapter(request),
-                        new WebResourceResponse(response.getMimeType(), response.getCharset(),
-                                response.getStatusCode(), response.getReasonPhrase(),
-                                response.getResponseHeaders(), response.getData()));
-            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                GlueApiHelperForM.onReceivedHttpError(mWebViewClient, mWebView, request, response);
-            }
-            // Otherwise, the API does not exist, so do nothing.
-        } finally {
-            TraceEvent.end("WebViewContentsClientAdapter.onReceivedHttpError");
-        }
-    }
-
-    /**
      * @see ContentViewClient#onReceivedTitle(String)
      */
     @Override
@@ -1207,14 +1018,6 @@
         }
     }
 
-    // TODO(tobiasjs) connect to support app-settable callbacks.
-    @Override
-    public void onRendererUnresponsive(final AwRenderProcess renderProcess) {}
-
-    // TODO(tobiasjs) connect to support app-settable callbacks.
-    @Override
-    public void onRendererResponsive(final AwRenderProcess renderProcess) {}
-
     @Override
     public boolean onRenderProcessGone(final AwRenderProcessGoneDetail detail) {
         // WebViewClient.onRenderProcessGone was added in O.
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java
index 2bec06a..9673a0f 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java
@@ -15,6 +15,8 @@
 import android.util.SparseArray;
 import android.view.View;
 
+import org.chromium.android_webview.AwDrawFnImpl;
+
 import java.lang.reflect.Method;
 
 /**
@@ -38,7 +40,7 @@
      * Copy of {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate}'s interface.
      * See {@link WebViewDelegateFactory} for the reasons why this copy is needed.
      */
-    interface WebViewDelegate {
+    interface WebViewDelegate extends AwDrawFnImpl.DrawFnAccess {
         /** @see android.webkit.WebViewDelegate.OnTraceEnabledChangeListener */
         interface OnTraceEnabledChangeListener {
             void onTraceEnabledChange(boolean enabled);
@@ -213,6 +215,11 @@
         public String getDataDirectorySuffix() {
             return GlueApiHelperForP.getDataDirectorySuffix(mDelegate);
         }
+
+        @Override
+        public void drawWebViewFunctor(Canvas canvas, int functor) {
+            throw new RuntimeException();
+        }
     }
 
     /**
@@ -407,5 +414,10 @@
         public String getDataDirectorySuffix() {
             return null;
         }
+
+        @Override
+        public void drawWebViewFunctor(Canvas canvas, int functor) {
+            throw new RuntimeException();
+        }
     }
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
index ddf7b3f..abb8ac1 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -133,21 +133,6 @@
                     throw new RuntimeException("Cannot initialize WebView", e);
                 }
             });
-
-            // Only run cleanup task on N+ since on earlier versions there are no extra pak files.
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                // Cleanup task to remove unnecessary extra pak files (crbug.com/752510).
-                // TODO(zpeng): Remove cleanup code after at least M64 (crbug.com/756580).
-                AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
-                    File extraPaksDir = new File(PathUtils.getDataDirectory(), "paks");
-                    if (extraPaksDir.exists()) {
-                        for (File pakFile : extraPaksDir.listFiles()) {
-                            pakFile.delete();
-                        }
-                        extraPaksDir.delete();
-                    }
-                });
-            }
         }
     }
 
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 dcf13c8..4056d54 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -260,6 +260,12 @@
          * Create a GL functor associated with native context |context|.
          */
         NativeDrawGLFunctor createGLFunctor(long context);
+
+        /**
+         * Used for draw_fn functor. Only one of these methods need to return non-null.
+         * Prefer this over createGLFunctor.
+         */
+        AwDrawFnImpl.DrawFnAccess getDrawFnAccess();
     }
 
     /**
@@ -343,7 +349,7 @@
     private long mNativeAwContents;
     private final AwBrowserContext mBrowserContext;
     private ViewGroup mContainerView;
-    private AwGLFunctor mDrawFunctor;
+    private AwFunctor mDrawFunctor;
     private final Context mContext;
     private final int mAppTargetSdkVersion;
     private AwViewAndroidDelegate mViewAndroidDelegate;
@@ -778,7 +784,7 @@
                 if (isDestroyedOrNoOperation(NO_WARN)) return;
                 if (level >= TRIM_MEMORY_MODERATE) {
                     if (mDrawFunctor != null) {
-                        mDrawFunctor.deleteHardwareRenderer();
+                        mDrawFunctor.trimMemory();
                     }
                 }
                 nativeTrimMemory(mNativeAwContents, level, visible);
@@ -1046,6 +1052,11 @@
             drawable.onContainerViewChanged(newContainerView);
         }
         onContainerViewChanged();
+
+        // When switching between main view and fullscreen view the container's
+        // view needs to be synchronized to what the native side has otherwise
+        // it may force an unintended scroll to the top of the document.
+        mScrollOffsetManager.syncScrollToContainerView();
     }
 
     /**
@@ -1145,18 +1156,18 @@
         }
     }
 
-    private void setFunctor(AwGLFunctor functor) {
+    private void setFunctor(AwFunctor functor) {
         if (mDrawFunctor == functor) return;
-        AwGLFunctor oldFunctor = mDrawFunctor;
+        AwFunctor oldFunctor = mDrawFunctor;
         mDrawFunctor = functor;
         updateNativeAwGLFunctor();
 
-        if (oldFunctor != null) oldFunctor.releasedByContents();
+        if (oldFunctor != null) oldFunctor.destroy();
     }
 
     private void updateNativeAwGLFunctor() {
-        nativeSetAwGLFunctor(
-                mNativeAwContents, mDrawFunctor != null ? mDrawFunctor.getNativeAwGLFunctor() : 0);
+        nativeSetCompositorFrameConsumer(mNativeAwContents,
+                mDrawFunctor != null ? mDrawFunctor.getNativeCompositorFrameConsumer() : 0);
     }
 
     /* Common initialization routine for adopting a native AwContents instance into this
@@ -3376,7 +3387,7 @@
         // Only valid within software onDraw().
         private final Rect mClipBoundsTemporary = new Rect();
 
-        @SuppressLint("DrawAllocation") // For new AwGLFunctor.
+        @SuppressLint("DrawAllocation") // For new AwFunctor.
         @Override
         public void onDraw(Canvas canvas) {
             if (isDestroyedOrNoOperation(NO_WARN)) {
@@ -3393,7 +3404,15 @@
             }
 
             if (canvas.isHardwareAccelerated() && mDrawFunctor == null) {
-                setFunctor(new AwGLFunctor(mNativeDrawFunctorFactory, mContainerView));
+                AwFunctor newFunctor;
+                AwDrawFnImpl.DrawFnAccess drawFnAccess =
+                        mNativeDrawFunctorFactory.getDrawFnAccess();
+                if (drawFnAccess != null) {
+                    newFunctor = new AwDrawFnImpl(drawFnAccess);
+                } else {
+                    newFunctor = new AwGLFunctor(mNativeDrawFunctorFactory, mContainerView);
+                }
+                setFunctor(newFunctor);
             }
 
             mScrollOffsetManager.syncScrollOffsetFromOnDraw();
@@ -3426,7 +3445,7 @@
             }
             if (did_draw && canvas.isHardwareAccelerated()
                     && !ForceAuxiliaryBitmapRendering.sResult) {
-                did_draw = mDrawFunctor.requestDrawGL(canvas);
+                did_draw = mDrawFunctor.requestDraw(canvas);
             }
             if (did_draw) {
                 int scrollXDiff = mContainerView.getScrollX() - scrollX;
@@ -3773,7 +3792,8 @@
             InterceptNavigationDelegate navigationInterceptionDelegate,
             AutofillProvider autofillProvider);
     private native WebContents nativeGetWebContents(long nativeAwContents);
-    private native void nativeSetAwGLFunctor(long nativeAwContents, long nativeAwGLFunctor);
+    private native void nativeSetCompositorFrameConsumer(
+            long nativeAwContents, long nativeCompositorFrameConsumer);
 
     private native void nativeDocumentHasImages(long nativeAwContents, Message message);
     private native void nativeGenerateMHTML(
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java
index 0c85343..9c20328 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java
@@ -121,21 +121,6 @@
         nativeSetCheckClearTextPermitted(permitted);
     }
 
-    @CalledByNative
-    private static void proxyOverrideChanged(Runnable callback) {
-        if (callback == null) return;
-        callback.run();
-    }
-
-    public static void setProxyOverride(
-            String host, int port, String[] exclusionList, Runnable callback) {
-        nativeSetProxyOverride(host, port, exclusionList, callback);
-    }
-
-    public static void clearProxyOverride(Runnable callback) {
-        nativeClearProxyOverride(callback);
-    }
-
     /**
      * Return the first substring consisting of the address of a physical location.
      * @see {@link android.webkit.WebView#findAddress(String)}
@@ -162,7 +147,4 @@
     private static native void nativeSetSafeBrowsingWhitelist(
             String[] urls, Callback<Boolean> callback);
     private static native void nativeSetCheckClearTextPermitted(boolean permitted);
-    private static native void nativeSetProxyOverride(
-            String host, int port, String[] exclusionList, Runnable callback);
-    private static native void nativeClearProxyOverride(Runnable callback);
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwDrawFnImpl.java b/android_webview/java/src/org/chromium/android_webview/AwDrawFnImpl.java
new file mode 100644
index 0000000..cdbc5dc
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwDrawFnImpl.java
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import android.graphics.Canvas;
+
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * Implementation of draw_fn.h.
+ */
+@JNINamespace("android_webview")
+public class AwDrawFnImpl implements AwFunctor {
+    private long mNativeAwDrawFnImpl;
+    private final DrawFnAccess mAccess;
+    private final int mHandle;
+
+    /** Interface for inserting functor into canvas */
+    public interface DrawFnAccess { void drawWebViewFunctor(Canvas canvas, int functor); }
+
+    public AwDrawFnImpl(DrawFnAccess access) {
+        mAccess = access;
+        mNativeAwDrawFnImpl = nativeCreate();
+        mHandle = nativeGetFunctorHandle(mNativeAwDrawFnImpl);
+    }
+
+    @Override
+    public void destroy() {
+        assert mNativeAwDrawFnImpl != 0;
+        nativeReleaseHandle(mNativeAwDrawFnImpl);
+        // Native side is free to destroy itself after ReleaseHandle.
+        mNativeAwDrawFnImpl = 0;
+    }
+
+    public static void setDrawFnFunctionTable(long functionTablePointer) {
+        nativeSetDrawFnFunctionTable(functionTablePointer);
+    }
+
+    @Override
+    public long getNativeCompositorFrameConsumer() {
+        assert mNativeAwDrawFnImpl != 0;
+        return nativeGetCompositorFrameConsumer(mNativeAwDrawFnImpl);
+    }
+
+    @Override
+    public boolean requestDraw(Canvas canvas) {
+        assert mNativeAwDrawFnImpl != 0;
+        mAccess.drawWebViewFunctor(canvas, mHandle);
+        return true;
+    }
+
+    @Override
+    public void trimMemory() {}
+
+    private native int nativeGetFunctorHandle(long nativeAwDrawFnImpl);
+    private native long nativeGetCompositorFrameConsumer(long nativeAwDrawFnImpl);
+    private native void nativeReleaseHandle(long nativeAwDrawFnImpl);
+
+    private static native void nativeSetDrawFnFunctionTable(long functionTablePointer);
+    private static native long nativeCreate();
+}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwFunctor.java b/android_webview/java/src/org/chromium/android_webview/AwFunctor.java
new file mode 100644
index 0000000..16aebf0
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwFunctor.java
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import android.graphics.Canvas;
+
+/**
+ * Interface for functor implementation. This allows client to avoid differentiating between GL and
+ * Vulkan implementations.
+ */
+public interface AwFunctor {
+    /** Insert draw functor into recording canvas */
+    boolean requestDraw(Canvas canvas);
+
+    /** Return the raw native pointer to CompositorFrameConsumer */
+    long getNativeCompositorFrameConsumer();
+
+    /** Free memory */
+    void trimMemory();
+
+    /** Destroy on UI thread. Client should stop using CompositorFrameConsumer before this */
+    void destroy();
+}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java b/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java
index 2893030..7f71386 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwGLFunctor.java
@@ -19,7 +19,7 @@
  * the render node hierarchy.
  */
 @JNINamespace("android_webview")
-public class AwGLFunctor {
+public class AwGLFunctor implements AwFunctor {
     private final long mNativeAwGLFunctor;
     private final AwContents.NativeDrawGLFunctor mNativeDrawGLFunctor;
     private final ViewGroup mContainerView;
@@ -30,8 +30,7 @@
     public AwGLFunctor(
             AwContents.NativeDrawFunctorFactory nativeDrawFunctorFactory, ViewGroup containerView) {
         mNativeAwGLFunctor = nativeCreate(this);
-        mNativeDrawGLFunctor = nativeDrawFunctorFactory.createGLFunctor(
-                nativeGetAwDrawGLViewContext(mNativeAwGLFunctor));
+        mNativeDrawGLFunctor = nativeDrawFunctorFactory.createGLFunctor(mNativeAwGLFunctor);
         mContainerView = containerView;
         if (mNativeDrawGLFunctor.supportsDrawGLFunctorReleasedCallback()) {
             mFunctorReleasedCallback = () -> removeReference();
@@ -41,8 +40,10 @@
         addReference();
     }
 
-    public void releasedByContents() {
+    @Override
+    public void destroy() {
         assert mRefCount > 0;
+        nativeRemoveFromCompositorFrameProducer(mNativeAwGLFunctor);
         removeReference();
     }
 
@@ -50,12 +51,14 @@
         return nativeGetAwDrawGLFunction();
     }
 
-    public long getNativeAwGLFunctor() {
+    @Override
+    public long getNativeCompositorFrameConsumer() {
         assert mRefCount > 0;
-        return mNativeAwGLFunctor;
+        return nativeGetCompositorFrameConsumer(mNativeAwGLFunctor);
     }
 
-    public boolean requestDrawGL(Canvas canvas) {
+    @Override
+    public boolean requestDraw(Canvas canvas) {
         assert mRefCount > 0;
         boolean success = mNativeDrawGLFunctor.requestDrawGL(canvas, mFunctorReleasedCallback);
         if (success && mFunctorReleasedCallback != null) {
@@ -91,7 +94,8 @@
         mContainerView.invalidate();
     }
 
-    public void deleteHardwareRenderer() {
+    @Override
+    public void trimMemory() {
         assert mRefCount > 0;
         nativeDeleteHardwareRenderer(mNativeAwGLFunctor);
     }
@@ -106,7 +110,8 @@
     }
 
     private native void nativeDeleteHardwareRenderer(long nativeAwGLFunctor);
-    private native long nativeGetAwDrawGLViewContext(long nativeAwGLFunctor);
+    private native void nativeRemoveFromCompositorFrameProducer(long nativeAwGLFunctor);
+    private native long nativeGetCompositorFrameConsumer(long nativeAwGLFunctor);
 
     private static native long nativeGetAwDrawGLFunction();
     private static native void nativeDestroy(long nativeAwGLFunctor);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwProxyController.java b/android_webview/java/src/org/chromium/android_webview/AwProxyController.java
new file mode 100644
index 0000000..bb2df95
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwProxyController.java
@@ -0,0 +1,68 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import org.chromium.base.annotations.CalledByNativeUnchecked;
+import org.chromium.base.annotations.JNINamespace;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Manages proxy override functionality in WebView.
+ */
+@JNINamespace("android_webview")
+public class AwProxyController {
+    public AwProxyController() {}
+
+    public String setProxyOverride(
+            String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor) {
+        int length = (proxyRules == null ? 0 : proxyRules.length);
+        String[] urlSchemes = new String[length];
+        String[] proxyUrls = new String[length];
+        for (int i = 0; i < length; i++) {
+            // URL schemes
+            if (proxyRules[i][0] == null) {
+                urlSchemes[i] = "*";
+            } else {
+                urlSchemes[i] = proxyRules[i][0];
+            }
+            // proxy URLs
+            proxyUrls[i] = proxyRules[i][1];
+            if (proxyUrls[i] == null) {
+                return "Proxy rule " + i + " has a null url";
+            }
+        }
+        length = (bypassRules == null ? 0 : bypassRules.length);
+        for (int i = 0; i < length; i++) {
+            if (bypassRules[i] == null) {
+                return "Bypass rule " + i + " is null";
+            }
+        }
+        if (executor == null) {
+            return "Executor must not be null";
+        }
+
+        return nativeSetProxyOverride(urlSchemes, proxyUrls, bypassRules, listener, executor);
+    }
+
+    public String clearProxyOverride(Runnable listener, Executor executor) {
+        if (executor == null) {
+            return "Executor must not be null";
+        }
+
+        nativeClearProxyOverride(listener, executor);
+        return "";
+    }
+
+    @CalledByNativeUnchecked
+    private void proxyOverrideChanged(Runnable listener, Executor executor) {
+        if (listener == null) return;
+        executor.execute(listener);
+    }
+
+    private native String nativeSetProxyOverride(String[] urlSchemes, String[] proxyUrls,
+            String[] bypassRules, Runnable listener, Executor executor);
+    private native void nativeClearProxyOverride(Runnable listener, Executor executor);
+}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java b/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java
index 60eeb81..3f45eb3 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java
@@ -248,6 +248,10 @@
         mDelegate.scrollNativeTo(x, y);
     }
 
+    void syncScrollToContainerView() {
+        scrollContainerViewTo(mNativeScrollX, mNativeScrollY);
+    }
+
     int getScrollX() {
         return mNativeScrollX;
     }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java b/android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java
deleted file mode 100644
index dc2dcae..0000000
--- a/android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java
+++ /dev/null
@@ -1,92 +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.android_webview;
-
-import android.net.Uri;
-
-import org.chromium.base.Callback;
-import org.chromium.base.Log;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-/**
- * AwTokenBindingManager manages the token binding protocol.
- *
- * see https://tools.ietf.org/html/draft-ietf-tokbind-protocol-03
- *
- * The token binding protocol can be enabled for browser context
- * separately. However all webviews share the same browser context and do not
- * expose the browser context to the embedder app. As such, there is no way to
- * enable token binding manager for individual webviews.
- */
-@JNINamespace("android_webview")
-public final class AwTokenBindingManager {
-    private static final String TAG = "TokenBindingManager";
-    private static final String ELLIPTIC_CURVE = "EC";
-
-    public void enableTokenBinding() {
-        nativeEnableTokenBinding();
-    }
-
-    public void getKey(Uri origin, String[] spec, Callback<KeyPair> callback) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback can't be null");
-        }
-        nativeGetTokenBindingKey(origin.getHost(), callback);
-    }
-
-    public void deleteKey(Uri origin, Callback<Boolean> callback) {
-        if (origin == null) {
-            throw new IllegalArgumentException("origin can't be null");
-        }
-        // null callback is allowed
-        nativeDeleteTokenBindingKey(origin.getHost(), callback);
-    }
-
-    public void deleteAllKeys(Callback<Boolean> callback) {
-        // null callback is allowed
-        nativeDeleteAllTokenBindingKeys(callback);
-    }
-
-    @CalledByNative
-    private static void onKeyReady(
-            Callback<KeyPair> callback, byte[] privateKeyBytes, byte[] publicKeyBytes) {
-        if (privateKeyBytes == null || publicKeyBytes == null) {
-            callback.onResult(null);
-            return;
-        }
-        KeyPair keyPair = null;
-        try {
-            KeyFactory factory = KeyFactory.getInstance(ELLIPTIC_CURVE);
-            PrivateKey privateKey =
-                    factory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
-            PublicKey publicKey = factory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
-            keyPair = new KeyPair(publicKey, privateKey);
-        } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
-            Log.e(TAG, "Failed converting key ", ex);
-        }
-        callback.onResult(keyPair);
-    }
-
-    @CalledByNative
-    private static void onDeletionComplete(Callback<Boolean> callback) {
-        // At present, the native deletion complete callback always succeeds.
-        callback.onResult(true);
-    }
-
-    private native void nativeEnableTokenBinding();
-    private native void nativeGetTokenBindingKey(String host, Callback<KeyPair> callback);
-    private native void nativeDeleteTokenBindingKey(String host, Callback<Boolean> callback);
-    private native void nativeDeleteAllTokenBindingKeys(Callback<Boolean> callback);
-}
diff --git a/android_webview/java/src/org/chromium/android_webview/command_line/CommandLineUtil.java b/android_webview/java/src/org/chromium/android_webview/command_line/CommandLineUtil.java
index 37912baf..6610e6f 100644
--- a/android_webview/java/src/org/chromium/android_webview/command_line/CommandLineUtil.java
+++ b/android_webview/java/src/org/chromium/android_webview/command_line/CommandLineUtil.java
@@ -4,9 +4,9 @@
 
 package org.chromium.android_webview.command_line;
 
-import android.os.Build;
 import android.os.StrictMode;
 
+import org.chromium.base.BuildInfo;
 import org.chromium.base.CommandLine;
 
 /**
@@ -22,16 +22,12 @@
     public static final String CRASH_UPLOADS_ENABLED_FOR_TESTING_SWITCH =
             "enable-crash-reporter-for-testing";
 
-    public static boolean isBuildDebuggable() {
-        return !Build.TYPE.equals("user");
-    }
-
     /**
      * Initialize the CommandLine for WebView - this should be initialized on the same thread where
      * we subsequently access CommandLine.
      */
     public static void initCommandLine() {
-        if (isBuildDebuggable()) {
+        if (BuildInfo.isDebugAndroid()) {
             // Suppress the StrictMode violation as this codepath is only hit on debuggable builds.
             StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
             CommandLine.initFromFile(CommandLineUtil.WEBVIEW_COMMAND_LINE_FILE);
diff --git a/android_webview/java/strings/translations/android_webview_strings_bn.xtb b/android_webview/java/strings/translations/android_webview_strings_bn.xtb
index 257ac9a..a972422 100644
--- a/android_webview/java/strings/translations/android_webview_strings_bn.xtb
+++ b/android_webview/java/strings/translations/android_webview_strings_bn.xtb
@@ -2,5 +2,5 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="bn">
 <translation id="3572484393913897457">সিস্টেম ওয়েবভিউ লাইসেন্সগুলি</translation>
-<translation id="8916631167640856213">এই সংস্করণের Android এ এই কার্যকারিতাটি সমর্থিত নয়৷</translation>
+<translation id="8916631167640856213">এই ভার্সনের Android এ এই কার্যকারিতাটি সমর্থিত নয়৷</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java
index 66f62a0..d8f482ac 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 
 import android.support.test.filters.LargeTest;
 import android.view.KeyEvent;
+import android.webkit.JavascriptInterface;
 
 import org.junit.Assert;
 import org.junit.Rule;
@@ -22,6 +23,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.content_public.common.ContentUrlConstants;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -34,34 +36,47 @@
 
     private static final String TAG = "AwRendererUnresponsive";
 
+    private static class JSBlocker {
+        private CountDownLatch mLatch;
+        JSBlocker() {
+            mLatch = new CountDownLatch(1);
+        }
+
+        public void releaseBlock() {
+            mLatch.countDown();
+        }
+
+        @JavascriptInterface
+        public void block() throws Exception {
+            mLatch.await(AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        }
+    }
+
     private static class RendererTransientlyUnresponsiveTestAwContentsClient
             extends TestAwContentsClient {
         private CallbackHelper mUnresponsiveCallbackHelper;
         private CallbackHelper mResponsiveCallbackHelper;
+        private JSBlocker mBlocker;
 
         public RendererTransientlyUnresponsiveTestAwContentsClient() {
             mUnresponsiveCallbackHelper = new CallbackHelper();
             mResponsiveCallbackHelper = new CallbackHelper();
+            mBlocker = new JSBlocker();
         }
 
         void transientlyBlockBlinkThread(final AwContents awContents) {
             ThreadUtils.runOnUiThread(() -> {
-                // clang-format off
-                awContents.evaluateJavaScript(
-                        "let t0 = performance.now();\n" +
-                        "while(performance.now() < t0 + 6000 /*ms*/) {}",
-                        null);
-                // clang-format on
+                awContents.addJavascriptInterface(mBlocker, "blocker");
+                awContents.evaluateJavaScript("blocker.block();", null);
             });
         }
 
         void awaitRecovery() throws Exception {
-            // unresponsive signal should occur after 5 seconds, so wait for 6.
-            mUnresponsiveCallbackHelper.waitForCallback(0, 1, 6, TimeUnit.SECONDS);
+            mUnresponsiveCallbackHelper.waitForCallback(
+                    0, 1, AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             Assert.assertEquals(1, mUnresponsiveCallbackHelper.getCallCount());
-            // blink main thread is transiently blocked for 6 seconds; wait
-            // an additional 5 seconds.
-            mResponsiveCallbackHelper.waitForCallback(0, 1, 5, TimeUnit.SECONDS);
+            mResponsiveCallbackHelper.waitForCallback(
+                    0, 1, AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             Assert.assertEquals(1, mResponsiveCallbackHelper.getCallCount());
         }
 
@@ -75,6 +90,7 @@
             // onRendererResponsive should not have been called yet.
             Assert.assertEquals(0, mResponsiveCallbackHelper.getCallCount());
             mUnresponsiveCallbackHelper.notifyCalled();
+            mBlocker.releaseBlock();
         }
     }
 
@@ -85,25 +101,29 @@
 
         private CallbackHelper mUnresponsiveCallbackHelper;
         private CallbackHelper mTerminatedCallbackHelper;
+        private JSBlocker mBlocker;
 
         public RendererUnresponsiveTestAwContentsClient() {
             mUnresponsiveCallbackHelper = new CallbackHelper();
             mTerminatedCallbackHelper = new CallbackHelper();
+            mBlocker = new JSBlocker();
         }
 
         void permanentlyBlockBlinkThread(final AwContents awContents) {
-            ThreadUtils.runOnUiThread(() -> { awContents.evaluateJavaScript("while(1);", null); });
+            ThreadUtils.runOnUiThread(() -> {
+                awContents.addJavascriptInterface(mBlocker, "blocker");
+                awContents.evaluateJavaScript("blocker.block();", null);
+            });
         }
 
         void awaitRendererTermination() throws Exception {
-            // The input ack timeout is 5 seconds, and the unresponsive callback should retrigger at
-            // that interval, so wait for the expected multiple of 5 seconds, plus one second
-            // leeway.
-            mUnresponsiveCallbackHelper.waitForCallback(
-                    0, 2, 5 * UNRESPONSIVE_CALLBACK_COUNT + 1, TimeUnit.SECONDS);
-            Assert.assertEquals(2, mUnresponsiveCallbackHelper.getCallCount());
+            mUnresponsiveCallbackHelper.waitForCallback(0, UNRESPONSIVE_CALLBACK_COUNT,
+                    AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            Assert.assertEquals(
+                    UNRESPONSIVE_CALLBACK_COUNT, mUnresponsiveCallbackHelper.getCallCount());
 
-            mTerminatedCallbackHelper.waitForCallback(0, 1, 5, TimeUnit.SECONDS);
+            mTerminatedCallbackHelper.waitForCallback(
+                    0, 1, AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             Assert.assertEquals(1, mTerminatedCallbackHelper.getCallCount());
         }
 
@@ -127,6 +147,9 @@
             awContents.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
         });
     }
+
+    // This test requires the ability to terminate the renderer in order to recover from a
+    // permanently stuck blink main thread, so it can only run in multiprocess.
     @Test
     @Feature({"AndroidWebView"})
     @LargeTest
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java
index 3676079..abbd14e 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java
@@ -16,6 +16,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.android_webview.AwDebug;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 
 import java.io.File;
@@ -42,6 +43,7 @@
     @Test
     @SmallTest
     @Feature({"AndroidWebView", "Debug"})
+    @DisabledTest(message = "crbug.com/913515")
     public void testDump() throws Throwable {
         File f = File.createTempFile("dump", ".dmp");
         try {
@@ -56,6 +58,7 @@
     @Test
     @SmallTest
     @Feature({"AndroidWebView", "Debug"})
+    @DisabledTest(message = "crbug.com/913515")
     public void testDumpContainsWhitelistedKey() throws Throwable {
         File f = File.createTempFile("dump", ".dmp");
         try {
@@ -71,6 +74,7 @@
     @Test
     @SmallTest
     @Feature({"AndroidWebView", "Debug"})
+    @DisabledTest(message = "crbug.com/913515")
     public void testDumpDoesNotContainNonWhitelistedKey() throws Throwable {
         File f = File.createTempFile("dump", ".dmp");
         try {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java
new file mode 100644
index 0000000..96b6863
--- /dev/null
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium 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.android_webview.test;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.android_webview.AwContents;
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.Feature;
+import org.chromium.net.test.EmbeddedTestServer;
+import org.chromium.net.test.ServerCertificate;
+
+/**
+ * A test suite for WebView's network-related configuration. This tests WebView's default settings,
+ * which are configured by either AwURLRequestContextGetter or NetworkContext.
+ */
+@RunWith(AwJUnit4ClassRunner.class)
+public class AwNetworkConfigurationTest {
+    @Rule
+    public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
+
+    private AwTestContainerView mTestContainerView;
+    private TestAwContentsClient mContentsClient;
+    private AwTestContainerView mContainerView;
+    private AwContents mAwContents;
+
+    private EmbeddedTestServer mTestServer;
+
+    @Before
+    public void setUp() throws Exception {
+        mContentsClient = new TestAwContentsClient();
+        mTestContainerView = mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient);
+        mAwContents = mTestContainerView.getAwContents();
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView", "Network"})
+    public void testSHA1LocalAnchorsAllowed() throws Throwable {
+        mTestServer = EmbeddedTestServer.createAndStartHTTPSServer(
+                InstrumentationRegistry.getInstrumentation().getContext(),
+                ServerCertificate.CERT_SHA1_LEAF);
+        try {
+            CallbackHelper onReceivedSslErrorHelper = mContentsClient.getOnReceivedSslErrorHelper();
+            int count = onReceivedSslErrorHelper.getCallCount();
+            String url = mTestServer.getURL("/android_webview/test/data/hello_world.html");
+            mActivityTestRule.loadUrlSync(
+                    mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
+            // TODO(ntfschr): update this assertion whenever
+            // https://android.googlesource.com/platform/external/conscrypt/+/1d6a0b8453054b7dd703693f2ce2896ae061aee3
+            // rolls into an Android release, as this will mean Android intends to distrust SHA1
+            // (http://crbug.com/919749).
+            Assert.assertEquals("We should not have received any SSL errors", count,
+                    onReceivedSslErrorHelper.getCallCount());
+        } finally {
+            mTestServer.stopAndDestroyServer();
+        }
+    }
+}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java
index d1609ab..ba695e6 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java
@@ -115,8 +115,8 @@
         Assert.assertEquals(BAD_HTML_URL, request.url);
         Assert.assertEquals("GET", request.method);
         Assert.assertNotNull(request.requestHeaders);
-        // No actual request has been made, as the host name can't be resolved.
-        Assert.assertTrue(request.requestHeaders.isEmpty());
+        // request headers may or may not be empty, this is an implementation detail,
+        // in the network service code path they may e.g. contain user agent, crbug.com/893573.
         Assert.assertTrue(request.isMainFrame);
         Assert.assertFalse(request.hasUserGesture);
         AwWebResourceError error = onReceivedError2Helper.getError();
@@ -149,8 +149,8 @@
         Assert.assertEquals(BAD_HTML_URL, request.url);
         Assert.assertEquals("GET", request.method);
         Assert.assertNotNull(request.requestHeaders);
-        // No actual request has been made, as the host name can't be resolved.
-        Assert.assertTrue(request.requestHeaders.isEmpty());
+        // request headers may or may not be empty, this is an implementation detail,
+        // in the network service code path they may e.g. contain user agent, crbug.com/893573.
         Assert.assertTrue(request.isMainFrame);
         Assert.assertTrue(request.hasUserGesture);
         AwWebResourceError error = onReceivedError2Helper.getError();
@@ -176,8 +176,8 @@
         Assert.assertEquals(BAD_HTML_URL, request.url);
         Assert.assertEquals("GET", request.method);
         Assert.assertNotNull(request.requestHeaders);
-        // No actual request has been made, as the host name can't be resolved.
-        Assert.assertTrue(request.requestHeaders.isEmpty());
+        // request headers may or may not be empty, this is an implementation detail,
+        // in the network service code path they may e.g. contain user agent, crbug.com/893573.
         Assert.assertFalse(request.isMainFrame);
         Assert.assertFalse(request.hasUserGesture);
         AwWebResourceError error = onReceivedError2Helper.getError();
@@ -214,8 +214,8 @@
         Assert.assertEquals(BAD_HTML_URL, request.url);
         Assert.assertEquals("GET", request.method);
         Assert.assertNotNull(request.requestHeaders);
-        // No actual request has been made, as the host name can't be resolved.
-        Assert.assertTrue(request.requestHeaders.isEmpty());
+        // request headers may or may not be empty, this is an implementation detail,
+        // in the network service code path they may e.g. contain user agent, crbug.com/893573.
         Assert.assertFalse(request.isMainFrame);
         Assert.assertTrue(request.hasUserGesture);
         AwWebResourceError error = onReceivedError2Helper.getError();
@@ -242,8 +242,8 @@
         Assert.assertEquals(imageUrl, request.url);
         Assert.assertEquals("GET", request.method);
         Assert.assertNotNull(request.requestHeaders);
-        // No actual request has been made, as the host name can't be resolved.
-        Assert.assertTrue(request.requestHeaders.isEmpty());
+        // request headers may or may not be empty, this is an implementation detail,
+        // in the network service code path they may e.g. contain user agent, crbug.com/893573.
         Assert.assertFalse(request.isMainFrame);
         Assert.assertFalse(request.hasUserGesture);
         AwWebResourceError error = onReceivedError2Helper.getError();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
index f6dd08c..88adeae 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
@@ -123,6 +123,32 @@
         }
     }
 
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView"})
+    public void testEmbedderCanSeeRestrictedCookies() throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        try {
+            // Set a cookie with the httponly flag, one with samesite=Strict, and one with
+            // samesite=Lax, to ensure that they are all visible to CookieManager in the app.
+            String cookies[] = {"httponly=foo1; HttpOnly", "strictsamesite=foo2; SameSite=Strict",
+                    "laxsamesite=foo3; SameSite=Lax"};
+            List<Pair<String, String>> responseHeaders = new ArrayList<Pair<String, String>>();
+            for (String cookie : cookies) {
+                responseHeaders.add(Pair.create("Set-Cookie", cookie));
+            }
+            String url = webServer.setResponse("/", "test", responseHeaders);
+            mActivityTestRule.loadUrlSync(
+                    mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
+            waitForCookie(url);
+            String cookie = mCookieManager.getCookie(url);
+            Assert.assertNotNull(cookie);
+            validateCookies(cookie, "httponly", "strictsamesite", "laxsamesite");
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
     private void setCookieWithJavaScript(final String name, final String value)
             throws Throwable {
         JSUtils.executeJavaScriptAndWaitForResult(InstrumentationRegistry.getInstrumentation(),
@@ -807,7 +833,7 @@
             foundCookieNames.add(cookie.substring(0, cookie.indexOf("=")).trim());
         }
         List<String> expectedCookieNamesList = Arrays.asList(expectedCookieNames);
-        Assert.assertEquals(foundCookieNames.size(), expectedCookieNamesList.size());
+        Assert.assertEquals(expectedCookieNamesList.size(), foundCookieNames.size());
         Assert.assertTrue(foundCookieNames.containsAll(expectedCookieNamesList));
     }
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
index 499a0a0..3057d79 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
@@ -31,8 +31,10 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"memlog=browser", "memlog-stack-mode=native-include-thread-names"})
-    public void testModeBrowser() throws Exception {
+    @CommandLineFlags.Add({"memlog=browser", "memlog-stack-mode=native-include-thread-names",
+            "memlog-sampling-rate=1"})
+    public void
+    testModeBrowser() throws Exception {
         HeapProfilingTestShim shim = new HeapProfilingTestShim();
         Assert.assertTrue(
                 shim.runTestForMode("browser", false, "native-include-thread-names", false, false));
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java
index 3df5276..6a16506 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java
@@ -13,6 +13,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.android_webview.AwContents;
+import org.chromium.base.FileUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.net.test.util.TestWebServer;
 
@@ -40,7 +41,7 @@
                                                 .getCacheDir()
                                                 .getPath(),
                 "org.chromium.android_webview");
-        deleteDirectory(webViewCacheDir);
+        FileUtils.recursivelyDeleteFile(webViewCacheDir);
 
         mActivityTestRule.startBrowserProcess();
         final TestAwContentsClient contentClient = new TestAwContentsClient();
@@ -66,12 +67,4 @@
         Assert.assertTrue(webViewCacheDir.isDirectory());
         Assert.assertTrue(webViewCacheDir.list().length > 0);
     }
-
-    private void deleteDirectory(File dir) throws Exception {
-        if (!dir.exists()) return;
-        Assert.assertTrue(dir.isDirectory());
-        Process rmrf = Runtime.getRuntime().exec("rm -rf " + dir.getAbsolutePath());
-        rmrf.waitFor();
-        Assert.assertFalse(dir.exists());
-    }
 }
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 7b871f7..b892708 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
@@ -143,6 +143,11 @@
         private static final long CHECK_DELTA_US = 10;
 
         @Override
+        public String getSafetyNetId() {
+            return "";
+        }
+
+        @Override
         public boolean init(Observer result) {
             return init(result, false);
         }
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index 65c016e..0addc54 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -34,7 +34,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "cc/base/switches.h"
 #include "components/autofill/core/common/autofill_features.h"
-#include "components/crash/content/app/breakpad_linux.h"
 #include "components/crash/core/common/crash_key.h"
 #include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h"
 #include "components/services/heap_profiling/public/cpp/allocator_shim.h"
@@ -241,7 +240,6 @@
         command_line.GetSwitchValueASCII(switches::kLang));
   }
 
-  int crash_signal_fd = -1;
   if (process_type == switches::kRendererProcess) {
     auto* global_descriptors = base::GlobalDescriptors::GetInstance();
     int pak_fd = global_descriptors->Get(kAndroidWebViewLocalePakDescriptor);
@@ -260,19 +258,9 @@
       ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
           base::File(pak_fd), pak_region, pak_info.second);
     }
-
-    crash_signal_fd =
-        global_descriptors->Get(kAndroidWebViewCrashSignalDescriptor);
-  }
-  if (is_browser_process) {
-    if (command_line.HasSwitch(switches::kWebViewSandboxedRenderer)) {
-      process_type = breakpad::kBrowserProcessType;
-    } else {
-      process_type = breakpad::kWebViewSingleProcessType;
-    }
   }
 
-  crash_reporter::EnableCrashReporter(process_type, crash_signal_fd);
+  crash_reporter::EnableCrashReporter(process_type);
 
   base::android::BuildInfo* android_build_info =
       base::android::BuildInfo::GetInstance();
@@ -298,12 +286,6 @@
     int exit_code = browser_runner_->Initialize(main_function_params);
     DCHECK_LT(exit_code, 0);
 
-    // At this point the content client has received the GPU info required
-    // to create a GPU fingerpring, and we can pass it to the microdump
-    // crash handler on the same thread as the crash handler was initialized.
-    crash_reporter::AddGpuFingerprintToMicrodumpCrashHandler(
-        content_client_.gpu_fingerprint());
-
     // Return 0 so that we do NOT trigger the default behavior. On Android, the
     // UI message loop is managed by the Java application.
     return 0;
@@ -344,7 +326,7 @@
   pak_file_path = pak_file_path.AppendASCII("resources.pak");
   ui::LoadMainAndroidPackFile("assets/resources.pak", pak_file_path);
 
-  aw_feature_list_creator_->CreateFetureListAndFieldTrials();
+  aw_feature_list_creator_->CreateFeatureListAndFieldTrials();
 }
 
 content::ContentBrowserClient* AwMainDelegate::CreateContentBrowserClient() {
diff --git a/android_webview/public/browser/draw_fn.h b/android_webview/public/browser/draw_fn.h
new file mode 100644
index 0000000..9aa029866
--- /dev/null
+++ b/android_webview/public/browser/draw_fn.h
@@ -0,0 +1,208 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_
+#define ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_
+
+#include <vulkan/vulkan.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// In order to make small changes backwards compatible, all structs passed from
+// android to chromium are versioned.
+//
+// 1 is Android Q. This matches kAwDrawGLInfoVersion version 3.
+static const int kAwDrawFnVersion = 1;
+
+struct AwDrawFn_OnSyncParams {
+  int version;
+
+  bool apply_force_dark;
+};
+
+struct AwDrawFn_DrawGLParams {
+  int version;
+
+  // Input: current clip rect in surface coordinates. Reflects the current state
+  // of the OpenGL scissor rect. Both the OpenGL scissor rect and viewport are
+  // set by the caller of the draw function and updated during View animations.
+  int clip_left;
+  int clip_top;
+  int clip_right;
+  int clip_bottom;
+
+  // Input: current width/height of destination surface.
+  int width;
+  int height;
+
+  // Input: is the View rendered into an independent layer.
+  // If false, the surface is likely to hold to the full screen contents, with
+  // the scissor box set by the caller to the actual View location and size.
+  // Also the transformation matrix will contain at least a translation to the
+  // position of the View to render, plus any other transformations required as
+  // part of any ongoing View animation. View translucency (alpha) is ignored,
+  // although the framework will set is_layer to true for non-opaque cases.
+  // Can be requested via the View.setLayerType(View.LAYER_TYPE_NONE, ...)
+  // Android API method.
+  //
+  // If true, the surface is dedicated to the View and should have its size.
+  // The viewport and scissor box are set by the caller to the whole surface.
+  // Animation transformations are handled by the caller and not reflected in
+  // the provided transformation matrix. Translucency works normally.
+  // Can be requested via the View.setLayerType(View.LAYER_TYPE_HARDWARE, ...)
+  // Android API method.
+  bool is_layer;
+
+  // Input: current transformation matrix in surface pixels.
+  // Uses the column-based OpenGL matrix format.
+  float transform[16];
+};
+
+struct AwDrawFn_InitVkParams {
+  int version;
+  VkInstance instance;
+  VkPhysicalDevice physical_device;
+  VkDevice device;
+  VkQueue queue;
+  uint32_t graphics_queue_index;
+  uint32_t instance_version;
+  const char* const* enabled_instance_extension_names;
+  uint32_t enabled_instance_extension_names_length;
+  const char* const* enabled_device_extension_names;
+  uint32_t enabled_device_extension_names_length;
+  // Only one of device_features and device_features_2 should be non-null.
+  // If both are null then no features are enabled.
+  VkPhysicalDeviceFeatures* device_features;
+  VkPhysicalDeviceFeatures2* device_features_2;
+};
+
+struct AwDrawFn_DrawVkParams {
+  int version;
+
+  // Input: current width/height of destination surface.
+  int width;
+  int height;
+
+  // Input: is the render target a FBO
+  bool is_layer;
+
+  // Input: current transform matrix
+  float transform[16];
+
+  // Input WebView should do its main compositing draws into this. It cannot do
+  // anything that would require stopping the render pass.
+  VkCommandBuffer secondary_command_buffer;
+
+  // Input: The main color attachment index where secondary_command_buffer will
+  // eventually be submitted.
+  uint32_t color_attachment_index;
+
+  // Input: A render pass which will be compatible to the one which the
+  // secondary_command_buffer will be submitted into.
+  VkRenderPass compatible_render_pass;
+
+  // Input: Format of the destination surface.
+  VkFormat format;
+
+  // Input: Color space parameters.
+  float transfer_function_g;
+  float transfer_function_a;
+  float transfer_function_b;
+  float transfer_function_c;
+  float transfer_function_d;
+  float transfer_function_e;
+  float transfer_function_f;
+  float color_space_matrix[9];
+
+  // Input: current clip rect
+  int clip_left;
+  int clip_top;
+  int clip_right;
+  int clip_bottom;
+};
+
+struct AwDrawFn_PostDrawVkParams {
+  int version;
+};
+
+// Called on render thread while UI thread is blocked. Called for both GL and
+// VK.
+typedef void AwDrawFn_OnSync(int functor,
+                             void* data,
+                             AwDrawFn_OnSyncParams* params);
+
+// Called on render thread when either the context is destroyed _or_ when the
+// functor's last reference goes away. Will always be called with an active
+// context. Called for both GL and VK.
+typedef void AwDrawFn_OnContextDestroyed(int functor, void* data);
+
+// Called on render thread when the last reference to the handle goes away and
+// the handle is considered irrevocably destroyed. Will always be preceded by
+// a call to OnContextDestroyed if this functor had ever been drawn. Called for
+// both GL and VK.
+typedef void AwDrawFn_OnDestroyed(int functor, void* data);
+
+// Only called for GL.
+typedef void AwDrawFn_DrawGL(int functor,
+                             void* data,
+                             AwDrawFn_DrawGLParams* params);
+
+// Initialize vulkan state. Needs to be called again after any
+// OnContextDestroyed. Only called for Vulkan.
+typedef void AwDrawFn_InitVk(int functor,
+                             void* data,
+                             AwDrawFn_InitVkParams* params);
+
+// Only called for Vulkan.
+typedef void AwDrawFn_DrawVk(int functor,
+                             void* data,
+                             AwDrawFn_DrawVkParams* params);
+
+// Only called for Vulkan.
+typedef void AwDrawFn_PostDrawVk(int functor,
+                                 void* data,
+                                 AwDrawFn_PostDrawVkParams* params);
+
+struct AwDrawFnFunctorCallbacks {
+  // No version here since this is passed from chromium to android.
+  AwDrawFn_OnSync* on_sync;
+  AwDrawFn_OnContextDestroyed* on_context_destroyed;
+  AwDrawFn_OnDestroyed* on_destroyed;
+  AwDrawFn_DrawGL* draw_gl;
+  AwDrawFn_InitVk* init_vk;
+  AwDrawFn_DrawVk* draw_vk;
+  AwDrawFn_PostDrawVk* post_draw_vk;
+};
+
+enum AwDrawFnRenderMode {
+  AW_DRAW_FN_RENDER_MODE_OPENGL_ES = 0,
+  AW_DRAW_FN_RENDER_MODE_VULKAN = 1,
+};
+
+// Get the render mode. Result is static for the process.
+typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void);
+
+// Create a functor. |functor_callbacks| should be valid until OnDestroyed.
+typedef int AwDrawFn_CreateFunctor(void* data,
+                                   AwDrawFnFunctorCallbacks* functor_callbacks);
+
+// May be called on any thread to signal that the functor should be destroyed.
+// The functor will receive an onDestroyed when the last usage of it is
+// released, and it should be considered alive & active until that point.
+typedef void AwDrawFn_ReleaseFunctor(int functor);
+
+struct AwDrawFnFunctionTable {
+  int version;
+  AwDrawFn_QueryRenderMode* query_render_mode;
+  AwDrawFn_CreateFunctor* create_functor;
+  AwDrawFn_ReleaseFunctor* release_functor;
+};
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_
diff --git a/android_webview/public/browser/draw_gl.h b/android_webview/public/browser/draw_gl.h
index 175d291..7b48921 100644
--- a/android_webview/public/browser/draw_gl.h
+++ b/android_webview/public/browser/draw_gl.h
@@ -33,9 +33,9 @@
   // Input: tells the draw function what action to perform.
   enum Mode {
     kModeDraw = 0,
-    kModeProcess,
-    kModeProcessNoContext,
-    kModeSync,
+    kModeProcess = 1,
+    kModeProcessNoContext = 2,
+    kModeSync = 3,
   } mode;
 
   // Input: current clip rect in surface coordinates. Reflects the current state
@@ -83,9 +83,9 @@
                                 AwDrawGLInfo* draw_info,
                                 void* spare);
 enum AwMapMode {
-  MAP_READ_ONLY,
-  MAP_WRITE_ONLY,
-  MAP_READ_WRITE,
+  MAP_READ_ONLY = 0,
+  MAP_WRITE_ONLY = 1,
+  MAP_READ_WRITE = 2,
 };
 
 // Called to create a GraphicBuffer
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index 0235457..7987ac7 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -193,8 +193,9 @@
 
 void AwContentRendererClient::PrepareErrorPage(
     content::RenderFrame* render_frame,
-    const blink::WebURLRequest& failed_request,
     const blink::WebURLError& error,
+    const std::string& http_method,
+    bool ignoring_cache,
     std::string* error_html) {
   std::string err;
   if (error.reason() == net::ERR_TEMPORARILY_THROTTLED)
@@ -206,7 +207,7 @@
     return;
 
   // Create the error page based on the error reason.
-  GURL gurl(failed_request.Url());
+  GURL gurl(error.url());
   std::string url_string = gurl.possibly_invalid_spec();
   int reason_id = IDS_AW_WEBPAGE_CAN_NOT_BE_LOADED;
 
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index 9c6906e..f6ae6dc 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -38,8 +38,9 @@
   void RenderViewCreated(content::RenderView* render_view) override;
   bool HasErrorPage(int http_status_code) override;
   void PrepareErrorPage(content::RenderFrame* render_frame,
-                        const blink::WebURLRequest& failed_request,
                         const blink::WebURLError& error,
+                        const std::string& http_method,
+                        bool ignoring_cache,
                         std::string* error_html) override;
   unsigned long long VisitedLinkHash(const char* canonical_url,
                                      size_t length) override;
diff --git a/android_webview/renderer/aw_render_frame_ext.cc b/android_webview/renderer/aw_render_frame_ext.cc
index d2fc7c5..71550a2 100644
--- a/android_webview/renderer/aw_render_frame_ext.cc
+++ b/android_webview/renderer/aw_render_frame_ext.cc
@@ -79,8 +79,9 @@
 
   if (spec.starts_with(prefix)) {
     url::RawCanonOutputW<1024> output;
-    url::DecodeURLEscapeSequences(spec.data() + prefix.length(),
-                                  spec.length() - prefix.length(), &output);
+    url::DecodeURLEscapeSequences(
+        spec.data() + prefix.length(), spec.length() - prefix.length(),
+        url::DecodeURLMode::kUTF8OrIsomorphic, &output);
     *dest =
         base::UTF16ToUTF8(base::StringPiece16(output.data(), output.length()));
     return true;
@@ -271,7 +272,7 @@
     return;
 
   // Hide selection and autofill popups.
-  webview->HidePopups();
+  webview->CancelPagePopup();
   webview->SetTextZoomFactor(zoom_factor);
 }
 
@@ -292,11 +293,11 @@
 }
 
 void AwRenderFrameExt::OnSetBackgroundColor(SkColor c) {
-  blink::WebFrameWidget* web_frame_widget = GetWebFrameWidget();
-  if (!web_frame_widget)
+  blink::WebView* webview = GetWebView();
+  if (!webview)
     return;
 
-  web_frame_widget->SetBaseBackgroundColor(c);
+  webview->SetBaseBackgroundColor(c);
 }
 
 void AwRenderFrameExt::OnSmoothScroll(int target_x,
diff --git a/android_webview/support_library/BUILD.gn b/android_webview/support_library/BUILD.gn
index 0dcebcb..48f7933 100644
--- a/android_webview/support_library/BUILD.gn
+++ b/android_webview/support_library/BUILD.gn
@@ -8,6 +8,7 @@
 android_library("support_lib_glue_java") {
   java_files = [
     "java/src/org/chromium/support_lib_glue/IsomorphicAdapter.java",
+    "java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java",
     "java/src/org/chromium/support_lib_glue/SupportLibReflectionUtil.java",
     "java/src/org/chromium/support_lib_glue/SupportLibServiceWorkerClientAdapter.java",
     "java/src/org/chromium/support_lib_glue/SupportLibServiceWorkerControllerAdapter.java",
@@ -20,6 +21,7 @@
     "java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java",
     "java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java",
     "java/src/org/chromium/support_lib_glue/SupportLibWebViewRendererAdapter.java",
+    "java/src/org/chromium/support_lib_glue/SupportLibWebViewRendererClientAdapter.java",
     "java/src/org/chromium/support_lib_glue/SupportLibWebkitToCompatConverterAdapter.java",
   ]
 
diff --git a/android_webview/support_library/boundary_interfaces/BUILD.gn b/android_webview/support_library/boundary_interfaces/BUILD.gn
index c43edc3..2111854 100644
--- a/android_webview/support_library/boundary_interfaces/BUILD.gn
+++ b/android_webview/support_library/boundary_interfaces/BUILD.gn
@@ -9,6 +9,7 @@
   java_files = [
     "src/org/chromium/support_lib_boundary/FeatureFlagHolderBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/IsomorphicObjectBoundaryInterface.java",
+    "src/org/chromium/support_lib_boundary/ProxyControllerBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/SafeBrowsingResponseBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/ServiceWorkerClientBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/ServiceWorkerControllerBoundaryInterface.java",
@@ -16,6 +17,7 @@
     "src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/TracingControllerBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/VisualStateCallbackBoundaryInterface.java",
+    "src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebMessageBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebMessageCallbackBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebMessagePortBoundaryInterface.java",
@@ -26,7 +28,7 @@
     "src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebViewRendererBoundaryInterface.java",
-    "src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java",
+    "src/org/chromium/support_lib_boundary/WebViewRendererClientBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java",
     "src/org/chromium/support_lib_boundary/util/Features.java",
   ]
diff --git a/android_webview/support_library/boundary_interfaces/OWNERS b/android_webview/support_library/boundary_interfaces/OWNERS
new file mode 100644
index 0000000..317642d
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/OWNERS
@@ -0,0 +1,2 @@
+# This file intentionally has no listed owners. If you're trying to make changes
+# to this folder, please see README.md first.
diff --git a/android_webview/support_library/boundary_interfaces/README.md b/android_webview/support_library/boundary_interfaces/README.md
new file mode 100644
index 0000000..acef0eb
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/README.md
@@ -0,0 +1,15 @@
+# Webkit Boundary Interfaces
+
+**Note:** the canonical copy of the boundary interfaces lives in the chromium
+repository; this subdirectory of chromium is mirrored into the Android project
+for use by the webkit AndroidX module.
+
+If you're reading this file in the Android repository, don't make changes in
+this folder. Please make changes in
+[chromium](https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/support_library/boundary_interfaces),
+or contact the OWNERS in `frameworks/support/webkit/`.
+
+If you're reading this file in the chromium repository, you should feel free to
+make changes. Please be aware that this folder has strict import requirements
+(enforced by `DEPS`), because it must continue to build when mirrored into
+Android.
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProxyControllerBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProxyControllerBoundaryInterface.java
new file mode 100644
index 0000000..f9abc59
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProxyControllerBoundaryInterface.java
@@ -0,0 +1,16 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.support_lib_boundary;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Boundary interface for ProxyController.
+ */
+public interface ProxyControllerBoundaryInterface {
+    void setProxyOverride(
+            String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor);
+    void clearProxyOverride(Runnable listener, Executor executor);
+}
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java
index 5511b39..d60a60dd 100644
--- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java
@@ -17,6 +17,4 @@
     void initSafeBrowsing(Context context, ValueCallback<Boolean> callback);
     void setSafeBrowsingWhitelist(List<String> hosts, ValueCallback<Boolean> callback);
     Uri getSafeBrowsingPrivacyPolicyUrl();
-    void setProxyOverride(String host, int port, String[] exclusionList, Runnable callback);
-    void clearProxyOverride(Runnable callback);
 }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java
index 9f8609c..c896d89 100644
--- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java
@@ -20,4 +20,7 @@
     WebViewClient getWebViewClient();
     WebChromeClient getWebChromeClient();
     /* WebViewRenderer */ InvocationHandler getWebViewRenderer();
+    /* WebViewRendererClient */ InvocationHandler getWebViewRendererClient();
+    void setWebViewRendererClient(
+            /* WebViewRendererClient */ InvocationHandler webViewRendererClient);
 }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java
index b971ed6f..15db689 100644
--- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java
@@ -17,4 +17,5 @@
     String[] getSupportedFeatures();
     /* SupportLibraryServiceWorkerController */ InvocationHandler getServiceWorkerController();
     /* SupportLibraryTracingController */ InvocationHandler getTracingController();
+    /* SupportLibraryProxyController */ InvocationHandler getProxyController();
 }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewRendererClientBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewRendererClientBoundaryInterface.java
new file mode 100644
index 0000000..043ca66
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewRendererClientBoundaryInterface.java
@@ -0,0 +1,17 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.support_lib_boundary;
+
+import android.webkit.WebView;
+
+import java.lang.reflect.InvocationHandler;
+
+/**
+ * Boundary interface for WebViewRendererClient.
+ */
+public interface WebViewRendererClientBoundaryInterface extends FeatureFlagHolderBoundaryInterface {
+    void onRendererUnresponsive(WebView view, /* WebViewRenderer */ InvocationHandler renderer);
+    void onRendererResponsive(WebView view, /* WebViewRenderer */ InvocationHandler renderer);
+}
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java
index 6badd3a..931cc89 100644
--- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 package org.chromium.support_lib_boundary.util;
 
+import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
 import android.os.Build;
 
@@ -16,6 +17,9 @@
 /**
  * A set of utility methods used for calling across the support library boundary.
  */
+// Although this is not enforced in chromium, this is a requirement enforced when this file is
+// mirrored into AndroidX. See http://b/120770118 for details.
+@SuppressLint("BanTargetApiAnnotation")
 public class BoundaryInterfaceReflectionUtil {
     /**
      * Check if an object is an instance of {@code className}, resolving {@code className} in
@@ -131,8 +135,12 @@
         }
     }
 
+    /**
+     * Check if this is a debuggable build of Android. Note: we copy BuildInfo's method because we
+     * cannot depend on the base-layer here (this folder is mirrored into Android).
+     */
     private static boolean isDebuggable() {
-        return !Build.TYPE.equals("user");
+        return "eng".equals(Build.TYPE) || "userdebug".equals(Build.TYPE);
     }
 
     /**
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
index b382c0b..cf5dbf1 100644
--- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
@@ -128,9 +128,9 @@
     // WebViewCompat.getWebChromeClient
     public static final String GET_WEB_CHROME_CLIENT = "GET_WEB_CHROME_CLIENT";
 
-    // WebViewCompat.setProxyOverride
-    // WebViewCompat.clearProxyOverride
-    public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE:2";
+    // ProxyController.setProxyOverride
+    // ProxyController.clearProxyOverride
+    public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE:3" + DEV_SUFFIX;
 
     // WebViewCompat.getWebViewRenderer
     public static final String GET_WEB_VIEW_RENDERER = "GET_WEB_VIEW_RENDERER";
@@ -143,4 +143,13 @@
     // TracingController.start
     // TracingController.stop
     public static final String TRACING_CONTROLLER_BASIC_USAGE = "TRACING_CONTROLLER_BASIC_USAGE";
+
+    // Renderer client set/getter and callbacks:
+    //
+    // WebView.getWebViewRendererClient
+    // WebView.setWebViewRendererClient
+    // WebViewRendererClient.onRendererUnresponsive()
+    // WebViewRendererClient.onRendererResponsive()
+    public static final String WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE =
+            "WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE";
 }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java
new file mode 100644
index 0000000..ebe0f6f
--- /dev/null
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java
@@ -0,0 +1,61 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.support_lib_glue;
+
+import org.chromium.android_webview.AwProxyController;
+import org.chromium.android_webview.WebViewChromiumRunQueue;
+import org.chromium.base.ThreadUtils;
+import org.chromium.support_lib_boundary.ProxyControllerBoundaryInterface;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Adapter between AwProxyController and ProxyControllerBoundaryInterface.
+ */
+public class SupportLibProxyControllerAdapter implements ProxyControllerBoundaryInterface {
+    private final WebViewChromiumRunQueue mRunQueue;
+    private final AwProxyController mProxyController;
+
+    public SupportLibProxyControllerAdapter(
+            WebViewChromiumRunQueue runQueue, AwProxyController proxyController) {
+        mRunQueue = runQueue;
+        mProxyController = proxyController;
+    }
+
+    @Override
+    public void setProxyOverride(
+            String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor) {
+        String result;
+        if (checkNeedsPost()) {
+            result = mRunQueue.runOnUiThreadBlocking(() -> {
+                return mProxyController.setProxyOverride(
+                        proxyRules, bypassRules, listener, executor);
+            });
+        } else {
+            result = mProxyController.setProxyOverride(proxyRules, bypassRules, listener, executor);
+        }
+        if (!result.isEmpty()) {
+            throw new IllegalArgumentException(result);
+        }
+    }
+
+    @Override
+    public void clearProxyOverride(Runnable listener, Executor executor) {
+        String result;
+        if (checkNeedsPost()) {
+            result = mRunQueue.runOnUiThreadBlocking(
+                    () -> { return mProxyController.clearProxyOverride(listener, executor); });
+        } else {
+            result = mProxyController.clearProxyOverride(listener, executor);
+        }
+        if (!result.isEmpty()) {
+            throw new IllegalArgumentException(result);
+        }
+    }
+
+    private static boolean checkNeedsPost() {
+        return !ThreadUtils.runningOnUiThread();
+    }
+}
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java
index 3ee5f06e..a9797ca 100644
--- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java
@@ -9,6 +9,7 @@
 import android.webkit.WebViewClient;
 
 import com.android.webview.chromium.SharedWebViewChromium;
+import com.android.webview.chromium.SharedWebViewRendererClientAdapter;
 
 import org.chromium.android_webview.AwContents;
 import org.chromium.support_lib_boundary.VisualStateCallbackBoundaryInterface;
@@ -20,6 +21,9 @@
 
 /**
  * Support library glue version of WebViewChromium.
+ *
+ * A new instance of this class is created transiently for every shared library
+ * WebViewCompat call. Do not store state here.
  */
 class SupportLibWebViewChromium implements WebViewProviderBoundaryInterface {
     private final SharedWebViewChromium mSharedWebViewChromium;
@@ -76,4 +80,21 @@
         return BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
                 new SupportLibWebViewRendererAdapter(mSharedWebViewChromium.getRenderProcess()));
     }
+
+    @Override
+    public /* WebViewRendererClient */ InvocationHandler getWebViewRendererClient() {
+        SharedWebViewRendererClientAdapter webViewRendererClientAdapter =
+                mSharedWebViewChromium.getWebViewRendererClientAdapter();
+        return webViewRendererClientAdapter != null
+                ? webViewRendererClientAdapter.getSupportLibInvocationHandler()
+                : null;
+    }
+
+    @Override
+    public void setWebViewRendererClient(
+            /* WebViewRendererClient */ InvocationHandler webViewRendererClient) {
+        mSharedWebViewChromium.setWebViewRendererClientAdapter(webViewRendererClient != null
+                        ? new SupportLibWebViewRendererClientAdapter(webViewRendererClient)
+                        : null);
+    }
 }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
index 83793ff..afc132c 100644
--- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
@@ -68,6 +68,7 @@
                     Features.GET_WEB_VIEW_RENDERER,
                     Features.WEB_VIEW_RENDERER_TERMINATE,
                     Features.TRACING_CONTROLLER_BASIC_USAGE,
+                    Features.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE + Features.DEV_SUFFIX,
             };
     // clang-format on
 
@@ -75,6 +76,7 @@
     private InvocationHandler mStatics;
     private InvocationHandler mServiceWorkerController;
     private InvocationHandler mTracingController;
+    private InvocationHandler mProxyController;
 
     public SupportLibWebViewChromiumFactory() {
         mCompatConverterAdapter = BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
@@ -116,17 +118,6 @@
         public Uri getSafeBrowsingPrivacyPolicyUrl() {
             return mSharedStatics.getSafeBrowsingPrivacyPolicyUrl();
         }
-
-        @Override
-        public void setProxyOverride(
-                String host, int port, String[] exclusionList, Runnable callback) {
-            mSharedStatics.setProxyOverride(host, port, exclusionList, callback);
-        }
-
-        @Override
-        public void clearProxyOverride(Runnable callback) {
-            mSharedStatics.clearProxyOverride(callback);
-        }
     }
 
     @Override
@@ -170,4 +161,16 @@
         }
         return mTracingController;
     }
+
+    @Override
+    public InvocationHandler getProxyController() {
+        synchronized (mAwInit.getLock()) {
+            if (mProxyController == null) {
+                mProxyController = BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
+                        new SupportLibProxyControllerAdapter(
+                                mAwInit.getRunQueue(), mAwInit.getAwProxyController()));
+            }
+        }
+        return mProxyController;
+    }
 }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewRendererClientAdapter.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewRendererClientAdapter.java
new file mode 100644
index 0000000..46de772
--- /dev/null
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewRendererClientAdapter.java
@@ -0,0 +1,61 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package org.chromium.support_lib_glue;
+
+import android.webkit.WebView;
+
+import com.android.webview.chromium.SharedWebViewRendererClientAdapter;
+
+import org.chromium.android_webview.AwRenderProcess;
+import org.chromium.support_lib_boundary.WebViewRendererClientBoundaryInterface;
+import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
+import org.chromium.support_lib_boundary.util.Features;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
+/**
+ * Support library glue renderer client callback dapter.
+ *
+ * A new instance of this class is created transiently for every shared library
+ * WebViewCompat call. Do not store state here.
+ */
+class SupportLibWebViewRendererClientAdapter extends SharedWebViewRendererClientAdapter {
+    private WebViewRendererClientBoundaryInterface mImpl;
+    private String[] mSupportedFeatures;
+
+    public SupportLibWebViewRendererClientAdapter(
+            /* WebViewRendererClient */ InvocationHandler invocationHandler) {
+        mImpl = BoundaryInterfaceReflectionUtil.castToSuppLibClass(
+                WebViewRendererClientBoundaryInterface.class, invocationHandler);
+        mSupportedFeatures = mImpl.getSupportedFeatures();
+    }
+
+    @Override
+    public /* WebViewRendererClient */ InvocationHandler getSupportLibInvocationHandler() {
+        return Proxy.getInvocationHandler(mImpl);
+    }
+
+    @Override
+    public void onRendererUnresponsive(final WebView webView, final AwRenderProcess renderProcess) {
+        if (!BoundaryInterfaceReflectionUtil.containsFeature(
+                    mSupportedFeatures, Features.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE)) {
+            return;
+        }
+        mImpl.onRendererUnresponsive(webView,
+                BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
+                        new SupportLibWebViewRendererAdapter(renderProcess)));
+    }
+
+    @Override
+    public void onRendererResponsive(final WebView webView, final AwRenderProcess renderProcess) {
+        if (!BoundaryInterfaceReflectionUtil.containsFeature(
+                    mSupportedFeatures, Features.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE)) {
+            return;
+        }
+        mImpl.onRendererResponsive(webView,
+                BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
+                        new SupportLibWebViewRendererAdapter(renderProcess)));
+    }
+}
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni
index 819907a..122ded8 100644
--- a/android_webview/system_webview_apk_tmpl.gni
+++ b/android_webview/system_webview_apk_tmpl.gni
@@ -3,9 +3,11 @@
 # found in the LICENSE file.
 
 import("//base/android/proguard/proguard.gni")
+import("//build/config/android/chrome_version.gni")
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 import("//build/config/locales.gni")
+import("//chrome/android/chrome_public_apk_tmpl.gni")
 
 template("system_webview_apk_tmpl") {
   android_apk(target_name) {
@@ -26,7 +28,10 @@
 
     shared_resources = true
 
-    if (!defined(use_trichrome_library) || !use_trichrome_library) {
+    _use_trichrome_library =
+        defined(use_trichrome_library) && use_trichrome_library
+
+    if (!_use_trichrome_library) {
       shared_libraries = [ "//android_webview:libwebviewchromium" ]
       if (build_apk_secondary_abi && android_64bit_target_cpu) {
         secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ]
@@ -35,17 +40,25 @@
       # Include placeholder libraries to ensure we are treated as the desired
       # architecture.
       if (android_64bit_target_cpu) {
-        shared_libraries = [ "//android_webview:monochrome" ]
-        if (build_apk_secondary_abi) {
-          secondary_native_lib_placeholders = [ "libdummy.so" ]
+        if (android_64bit_browser) {
+          native_lib_placeholders = [ "libdummy.so" ]
+          if (build_apk_secondary_abi) {
+            secondary_abi_shared_libraries = [
+              "//android_webview:monochrome($android_secondary_abi_toolchain)",
+            ]
+          }
+        } else {
+          shared_libraries = [ "//android_webview:monochrome" ]
+          if (build_apk_secondary_abi) {
+            secondary_native_lib_placeholders = [ "libdummy.so" ]
+          }
         }
       } else {
         native_lib_placeholders = [ "libdummy.so" ]
       }
     }
 
-    if (!defined(use_trichrome_library) || !use_trichrome_library ||
-        android_64bit_target_cpu) {
+    if (!_use_trichrome_library || android_64bit_target_cpu) {
       # 32-bit TrichromeWebView doesn't have a native library, so only do this
       # for other configs.
       native_lib_version_rule = "//build/util:chrome_version_json"
@@ -89,5 +102,16 @@
       png_to_webp = true
     }
     command_line_flags_file = "webview-command-line"
+
+    if (!defined(version_code)) {
+      if (_use_trichrome_library) {
+        version_code = trichrome_version_code
+      } else {
+        version_code = webview_version_code
+      }
+    }
+    if (!defined(version_name)) {
+      version_name = chrome_version_name
+    }
   }
 }
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index 49e22ae..2628d46 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -63,7 +63,7 @@
     "shell/src/org/chromium/android_webview/shell/AwShellApplication.java",
     "shell/src/org/chromium/android_webview/shell/AwShellResourceProvider.java",
     "shell/src/org/chromium/android_webview/shell/AwShellSwitches.java",
-    "shell/src/org/chromium/android_webview/shell/DrawGL.java",
+    "shell/src/org/chromium/android_webview/shell/DrawFn.java",
     "shell/src/org/chromium/android_webview/test/AwTestContainerView.java",
     "shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java",
     "shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java",
@@ -73,10 +73,7 @@
     "shell/src/org/chromium/android_webview/test/TestContentProvider.java",
   ]
 
-  shared_libraries = [
-    ":libdrawgl",
-    ":libstandalonelibwebviewchromium",
-  ]
+  shared_libraries = [ ":libstandalonelibwebviewchromium" ]
 
   native_lib_version_rule = "//build/util:chrome_version_json"
   _native_lib_file =
@@ -132,10 +129,12 @@
   testonly = true
   sources = [
     "../lib/webview_entry_point.cc",
+    "shell/src/draw_gl/draw_fn.cc",
   ]
   ldflags = [ "-Wl,-shared,-Bsymbolic" ]
   deps = [
     "//android_webview:common",
+    "//base",
     "//components/heap_profiling:test_support",
     "//components/minidump_uploader",
     "//content/public/test/android:content_native_test_support",
@@ -211,6 +210,7 @@
     "../javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java",
+    "../javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwPermissionManagerTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwQuotaManagerBridgeTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwScrollOffsetManagerTest.java",
@@ -342,6 +342,7 @@
     "../browser/net/aw_cookie_store_wrapper_unittest.cc",
     "../browser/net/aw_url_request_context_getter_unittest.cc",
     "../browser/net/input_stream_reader_unittest.cc",
+    "../browser/net_network_service/android_stream_reader_url_loader_unittest.cc",
     "../browser/permission/media_access_permission_request_unittest.cc",
     "../browser/permission/permission_request_handler_unittest.cc",
     "../browser/renderer_host/auto_login_parser_unittest.cc",
@@ -380,10 +381,3 @@
     "../unittestjava/src/org/chromium/android_webview/unittest/MockAwContentsClientBridge.java",
   ]
 }
-
-shared_library("libdrawgl") {
-  sources = [
-    "shell/src/draw_gl/draw_gl.cc",
-  ]
-  configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
-}
diff --git a/android_webview/test/embedded_test_server/aw_embedded_test_server.cc b/android_webview/test/embedded_test_server/aw_embedded_test_server.cc
index 26342c6..781384b8 100644
--- a/android_webview/test/embedded_test_server/aw_embedded_test_server.cc
+++ b/android_webview/test/embedded_test_server/aw_embedded_test_server.cc
@@ -219,8 +219,7 @@
 
 // static
 ScopedJavaLocalRef<jlongArray> JNI_AwEmbeddedTestServerImpl_GetHandlers(
-    JNIEnv* env,
-    const JavaParamRef<jclass>&) {
+    JNIEnv* env) {
   std::vector<int64_t> handlers = {
       reinterpret_cast<int64_t>(&HandleClickRedirect),
       reinterpret_cast<int64_t>(&HandleEchoHeaderAndSetData),
diff --git a/android_webview/test/shell/src/draw_gl/draw_fn.cc b/android_webview/test/shell/src/draw_gl/draw_fn.cc
new file mode 100644
index 0000000..e3a0abe
--- /dev/null
+++ b/android_webview/test/shell/src/draw_gl/draw_fn.cc
@@ -0,0 +1,160 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <jni.h>
+
+#include "android_webview/public/browser/draw_fn.h"
+#include "base/containers/flat_map.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/synchronization/lock.h"
+
+namespace {
+
+struct FunctorData {
+  int functor = 0;
+  void* data = nullptr;
+  AwDrawFnFunctorCallbacks* functor_callbacks = nullptr;
+  bool released = false;
+};
+
+class FunctorMap {
+ public:
+  int allocate(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
+    base::AutoLock lock(lock_);
+    int functor = next_functor_++;
+    map_.emplace(functor, FunctorData{functor, data, functor_callbacks});
+    return functor;
+  }
+
+  FunctorData get(int functor) {
+    base::AutoLock lock(lock_);
+    auto itr = map_.find(functor);
+    DCHECK(itr != map_.end());
+    return itr->second;
+  }
+
+  void mark_released(int functor) {
+    base::AutoLock lock(lock_);
+    auto itr = map_.find(functor);
+    DCHECK(itr != map_.end());
+    DCHECK(!itr->second.released);
+    itr->second.released = true;
+  }
+
+  void destroy_released() {
+    base::AutoLock lock(lock_);
+    for (auto itr = map_.begin(); itr != map_.end();) {
+      FunctorData& data = itr->second;
+      if (data.released) {
+        // Holding lock here, but not too terrible.
+        data.functor_callbacks->on_context_destroyed(data.functor, data.data);
+        data.functor_callbacks->on_destroyed(data.functor, data.data);
+        itr = map_.erase(itr);
+      } else {
+        DLOG(ERROR) << "Functor not released. Possibly leaking instead";
+        ++itr;
+      }
+    }
+  }
+
+ private:
+  base::Lock lock_;
+  base::flat_map<int, FunctorData> map_;
+  int next_functor_ = 1;
+};
+
+base::LazyInstance<FunctorMap>::Leaky g_map;
+
+AwDrawFnRenderMode QueryRenderMode() {
+  return AW_DRAW_FN_RENDER_MODE_OPENGL_ES;
+}
+
+int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
+  return g_map.Get().allocate(data, functor_callbacks);
+}
+
+void ReleaseFunctor(int functor) {
+  g_map.Get().mark_released(functor);
+}
+
+}  // namespace
+
+extern "C" {
+
+JNIEXPORT jlong JNICALL
+Java_org_chromium_android_1webview_shell_DrawFn_nativeGetDrawFnFunctionTable(
+    JNIEnv*,
+    jclass) {
+  static AwDrawFnFunctionTable table{
+      kAwDrawFnVersion,
+      &QueryRenderMode,
+      &CreateFunctor,
+      &ReleaseFunctor,
+  };
+  return reinterpret_cast<intptr_t>(&table);
+}
+
+JNIEXPORT void JNICALL
+Java_org_chromium_android_1webview_shell_DrawFn_nativeSync(
+    JNIEnv*,
+    jclass,
+    jint functor,
+    jboolean force_apply_dark) {
+  FunctorData data = g_map.Get().get(functor);
+  AwDrawFn_OnSyncParams params{kAwDrawFnVersion, force_apply_dark};
+  data.functor_callbacks->on_sync(functor, data.data, &params);
+}
+
+JNIEXPORT void JNICALL
+Java_org_chromium_android_1webview_shell_DrawFn_nativeDestroyReleased(JNIEnv*,
+                                                                      jclass) {
+  g_map.Get().destroy_released();
+}
+
+JNIEXPORT void JNICALL
+Java_org_chromium_android_1webview_shell_DrawFn_nativeDestroyed(JNIEnv*,
+                                                                jclass,
+                                                                jint functor) {}
+
+JNIEXPORT void JNICALL
+Java_org_chromium_android_1webview_shell_DrawFn_nativeDrawGL(JNIEnv*,
+                                                             jclass,
+                                                             jint functor,
+                                                             jint width,
+                                                             jint height,
+                                                             jint scroll_x,
+                                                             jint scroll_y) {
+  FunctorData data = g_map.Get().get(functor);
+  AwDrawFn_DrawGLParams params{kAwDrawFnVersion};
+  params.is_layer = false;
+  params.width = width;
+  params.height = height;
+  params.clip_left = 0;
+  params.clip_top = 0;
+  params.clip_bottom = height;
+  params.clip_right = width;
+  params.transform[0] = 1.0;
+  params.transform[1] = 0.0;
+  params.transform[2] = 0.0;
+  params.transform[3] = 0.0;
+
+  params.transform[4] = 0.0;
+  params.transform[5] = 1.0;
+  params.transform[6] = 0.0;
+  params.transform[7] = 0.0;
+
+  params.transform[8] = 0.0;
+  params.transform[9] = 0.0;
+  params.transform[10] = 1.0;
+  params.transform[11] = 0.0;
+
+  params.transform[12] = -scroll_x;
+  params.transform[13] = -scroll_y;
+  params.transform[14] = 0.0;
+  params.transform[15] = 1.0;
+  data.functor_callbacks->draw_gl(functor, data.data, &params);
+}
+
+}  // extern "C"
diff --git a/android_webview/test/shell/src/draw_gl/draw_gl.cc b/android_webview/test/shell/src/draw_gl/draw_gl.cc
deleted file mode 100644
index 260a3f5..0000000
--- a/android_webview/test/shell/src/draw_gl/draw_gl.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 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 <jni.h>
-
-#include "android_webview/public/browser/draw_gl.h"
-
-extern "C" {
-
-JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
-  return JNI_VERSION_1_4;
-}
-
-// This code goes into its own dynamic library, so we cannot depend on
-// any other components like base.
-JNIEXPORT void JNICALL
-    Java_org_chromium_android_1webview_shell_DrawGL_nativeDrawGL(
-        JNIEnv*,
-        jclass,
-        jlong draw_gl,
-        jlong view,
-        jint width,
-        jint height,
-        jint scroll_x,
-        jint scroll_y,
-        jint mode) {
-   AwDrawGLInfo draw_info;
-   draw_info.mode = static_cast<AwDrawGLInfo::Mode>(mode);
-   draw_info.version = kAwDrawGLInfoVersion;
-   draw_info.is_layer = false;
-   draw_info.width = width;
-   draw_info.height = height;
-   draw_info.clip_left = 0;
-   draw_info.clip_top = 0;
-   draw_info.clip_bottom = height;
-   draw_info.clip_right = width;
-   draw_info.transform[0] = 1.0;
-   draw_info.transform[1] = 0.0;
-   draw_info.transform[2] = 0.0;
-   draw_info.transform[3] = 0.0;
-
-   draw_info.transform[4] = 0.0;
-   draw_info.transform[5] = 1.0;
-   draw_info.transform[6] = 0.0;
-   draw_info.transform[7] = 0.0;
-
-   draw_info.transform[8] = 0.0;
-   draw_info.transform[9] = 0.0;
-   draw_info.transform[10] = 1.0;
-   draw_info.transform[11] = 0.0;
-
-   draw_info.transform[12] = -scroll_x;
-   draw_info.transform[13] = -scroll_y;
-   draw_info.transform[14] = 0.0;
-   draw_info.transform[15] = 1.0;
-   AwDrawGLFunction* draw_func = reinterpret_cast<AwDrawGLFunction*>(draw_gl);
-   draw_func(view, &draw_info, 0);
-}
-
-}
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawFn.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawFn.java
new file mode 100644
index 0000000..c35c06f
--- /dev/null
+++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawFn.java
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview.shell;
+
+/** draw_fn framework side implementation for tests. */
+public class DrawFn {
+    public static long getDrawFnFunctionTable() {
+        return nativeGetDrawFnFunctionTable();
+    }
+
+    public static void sync(int functor, boolean applyForceDark) {
+        nativeSync(functor, applyForceDark);
+    }
+
+    public static void destroyReleased() {
+        nativeDestroyReleased();
+    }
+
+    public static void drawGL(int functor, int width, int height, int scrollX, int scrollY) {
+        nativeDrawGL(functor, width, height, scrollX, scrollY);
+    }
+
+    private static native long nativeGetDrawFnFunctionTable();
+    private static native void nativeSync(int functor, boolean applyForceDark);
+    private static native void nativeDestroyReleased();
+    private static native void nativeDrawGL(
+            int functor, int width, int height, int scrollX, int scrollY);
+}
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawGL.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawGL.java
deleted file mode 100644
index bc5e429..0000000
--- a/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawGL.java
+++ /dev/null
@@ -1,18 +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.
-
-package org.chromium.android_webview.shell;
-
-/**
- * Provides an entry point to the native draw functor.
- */
-public class DrawGL {
-    public static void drawGL(long drawGL, long viewContext, int width, int height,
-            int scrollX, int scrollY, int mode) {
-        nativeDrawGL(drawGL, viewContext, width, height, scrollX, scrollY, mode);
-    }
-
-    private static native void nativeDrawGL(long drawGL, long viewContext,
-            int width, int height, int scrollX, int scrollY, int mode);
-}
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
index 39284c4..c19edf3 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
@@ -4,6 +4,7 @@
 
 package org.chromium.android_webview.test;
 
+import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -11,7 +12,9 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.opengl.GLSurfaceView;
+import android.os.Build;
 import android.os.Bundle;
+import android.view.DragEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
@@ -22,7 +25,8 @@
 import android.widget.FrameLayout;
 
 import org.chromium.android_webview.AwContents;
-import org.chromium.android_webview.shell.DrawGL;
+import org.chromium.android_webview.AwDrawFnImpl;
+import org.chromium.android_webview.shell.DrawFn;
 import org.chromium.content_public.browser.WebContents;
 
 import javax.microedition.khronos.egl.EGLConfig;
@@ -50,10 +54,9 @@
         // and drawGL on the rendering thread. The variables following
         // are protected by it.
         private final Object mSyncLock = new Object();
-        private boolean mFunctorAttached;
-        private boolean mNeedsProcessGL;
-        private boolean mNeedsDrawGL;
-        private boolean mWaitForCompletion;
+        private int mFunctor;
+        private boolean mSyncDone;
+        private boolean mPendingDestroy;
         private int mLastScrollX;
         private int mLastScrollY;
 
@@ -66,9 +69,6 @@
         private Runnable mReadyToRenderCallback;
         private Runnable mReadyToDetachCallback;
 
-        private long mDrawGL;
-        private long mViewContext;
-
         public HardwareView(Context context) {
             super(context);
             setEGLContextClientVersion(2); // GLES2
@@ -80,7 +80,7 @@
 
                 @Override
                 public void onDrawFrame(GL10 gl) {
-                    HardwareView.this.drawGL(mWidth, mHeight);
+                    HardwareView.this.onDrawFrame(mWidth, mHeight);
                 }
 
                 @Override
@@ -92,18 +92,12 @@
                 }
 
                 @Override
-                public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-                }
+                public void onSurfaceCreated(GL10 gl, EGLConfig config) {}
             });
 
             setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
         }
 
-        public void initialize(long drawGL) {
-            mDrawGL = drawGL;
-            mViewContext = 0;
-        }
-
         public boolean isReadyToRender() {
             return mHaveSurface;
         }
@@ -144,90 +138,61 @@
             }
         }
 
-        public void detachGLFunctor() {
+        public void awContentsDetached() {
             synchronized (mSyncLock) {
-                mFunctorAttached = false;
-                mNeedsProcessGL = false;
-                mNeedsDrawGL = false;
-                mWaitForCompletion = false;
-            }
-        }
-
-        public void requestRender(long viewContext, Canvas canvas, boolean waitForCompletion) {
-            synchronized (mSyncLock) {
-                assert viewContext != 0;
-                mViewContext = viewContext;
                 super.requestRender();
-                mFunctorAttached = true;
-                mWaitForCompletion = waitForCompletion;
-                if (canvas == null) {
-                    mNeedsProcessGL = true;
-                } else {
-                    mNeedsDrawGL = true;
-                    if (!waitForCompletion) {
-                        // Wait until SYNC is complete only.
-                        // Do this every time there was a new frame.
-                        try {
-                            while (mNeedsDrawGL) {
-                                mSyncLock.wait();
-                            }
-                        } catch (InterruptedException e) {
-                            // ...
-                        }
+                assert !mPendingDestroy;
+                mPendingDestroy = true;
+                try {
+                    while (!mPendingDestroy) {
+                        mSyncLock.wait();
                     }
-                }
-                if (waitForCompletion) {
-                    try {
-                        while (mWaitForCompletion) {
-                            mSyncLock.wait();
-                        }
-                    } catch (InterruptedException e) {
-                        // ...
-                    }
+                } catch (InterruptedException e) {
+                    // ...
                 }
             }
         }
 
-        public void drawGL(int width, int height) {
-            final boolean draw;
-            final boolean process;
-            final boolean waitForCompletion;
-            final long viewContext;
-
+        public void drawWebViewFunctor(int functor) {
             synchronized (mSyncLock) {
-                if (!mFunctorAttached) {
+                super.requestRender();
+                assert mFunctor == 0;
+                mFunctor = functor;
+                mSyncDone = false;
+                try {
+                    while (!mSyncDone) {
+                        mSyncLock.wait();
+                    }
+                } catch (InterruptedException e) {
+                    // ...
+                }
+            }
+        }
+
+        public void onDrawFrame(int width, int height) {
+            int functor;
+            int scrollX;
+            int scrollY;
+            synchronized (mSyncLock) {
+                functor = mFunctor;
+                mFunctor = 0;
+                scrollX = mLastScrollX;
+                scrollY = mLastScrollY;
+
+                if (functor != 0) {
+                    assert !mSyncDone;
+                    DrawFn.sync(functor, false);
+                    mSyncDone = true;
+                    mSyncLock.notifyAll();
+                } else if (mPendingDestroy) {
+                    DrawFn.destroyReleased();
+                    mPendingDestroy = false;
                     mSyncLock.notifyAll();
                     return;
                 }
-
-                draw = mNeedsDrawGL;
-                process = mNeedsProcessGL;
-                waitForCompletion = mWaitForCompletion;
-                viewContext = mViewContext;
-                if (draw) {
-                    DrawGL.drawGL(mDrawGL, viewContext, width, height, 0, 0, MODE_SYNC);
-                    mCommittedScrollX = mLastScrollX;
-                    mCommittedScrollY = mLastScrollY;
-                }
-                mNeedsDrawGL = false;
-                mNeedsProcessGL = false;
-                if (!waitForCompletion) {
-                    mSyncLock.notifyAll();
-                }
             }
-            if (process) {
-                DrawGL.drawGL(mDrawGL, viewContext, width, height, 0, 0, MODE_PROCESS);
-            }
-            if (process || draw) {
-                DrawGL.drawGL(mDrawGL, viewContext, width, height, mCommittedScrollX,
-                        mCommittedScrollY, MODE_DRAW);
-            }
-
-            if (waitForCompletion) {
-                synchronized (mSyncLock) {
-                    mWaitForCompletion = false;
-                    mSyncLock.notifyAll();
-                }
+            if (functor != 0) {
+                DrawFn.drawGL(functor, width, height, scrollX, scrollY);
             }
         }
     }
@@ -261,7 +226,7 @@
     public void initialize(AwContents awContents) {
         mAwContents = awContents;
         if (isBackedByHardwareView()) {
-            mHardwareView.initialize(AwContents.getAwDrawGLFunction());
+            AwDrawFnImpl.setDrawFnFunctionTable(DrawFn.getDrawFnFunctionTable());
         }
     }
 
@@ -305,6 +270,9 @@
         assert mAttachedContents;
         mAwContents.onDetachedFromWindow();
         mAttachedContents = false;
+        if (mHardwareView != null) {
+            mHardwareView.awContentsDetached();
+        }
     }
 
     @Override
@@ -436,48 +404,29 @@
         return mAwContents.performAccessibilityAction(action, arguments);
     }
 
+    @Override
+    @TargetApi(Build.VERSION_CODES.N)
+    public boolean onDragEvent(DragEvent event) {
+        return mAwContents.onDragEvent(event);
+    }
+
     private class NativeDrawFunctorFactory implements AwContents.NativeDrawFunctorFactory {
         @Override
-        public NativeDrawGLFunctor createGLFunctor(long context) {
-            return new NativeDrawGLFunctor(context);
+        public AwContents.NativeDrawGLFunctor createGLFunctor(long context) {
+            return null;
+        }
+
+        @Override
+        public AwDrawFnImpl.DrawFnAccess getDrawFnAccess() {
+            return new DrawFnAccess();
         }
     }
 
-    private class NativeDrawGLFunctor implements AwContents.NativeDrawGLFunctor {
-        private long mContext;
-
-        NativeDrawGLFunctor(long context) {
-            mContext = context;
-        }
-
+    private class DrawFnAccess implements AwDrawFnImpl.DrawFnAccess {
         @Override
-        public boolean supportsDrawGLFunctorReleasedCallback() {
-            return false;
-        }
-
-        @Override
-        public boolean requestDrawGL(Canvas canvas, Runnable releasedRunnable) {
-            assert releasedRunnable == null;
-            if (!isBackedByHardwareView()) return false;
-            mHardwareView.requestRender(mContext, canvas, false);
-            return true;
-        }
-
-        @Override
-        public boolean requestInvokeGL(View containerView, boolean waitForCompletion) {
-            if (!isBackedByHardwareView()) return false;
-            mHardwareView.requestRender(mContext, null, waitForCompletion);
-            return true;
-        }
-
-        @Override
-        public void detach(View containerView) {
-            if (isBackedByHardwareView()) mHardwareView.detachGLFunctor();
-        }
-
-        @Override
-        public void destroy() {
-            mContext = 0;
+        public void drawWebViewFunctor(Canvas canvas, int functor) {
+            assert isBackedByHardwareView();
+            mHardwareView.drawWebViewFunctor(functor);
         }
     }
 
diff --git a/android_webview/tools/apk_merger.py b/android_webview/tools/apk_merger.py
index 0e6eef4..14ef0d6 100755
--- a/android_webview/tools/apk_merger.py
+++ b/android_webview/tools/apk_merger.py
@@ -14,7 +14,7 @@
 
 To use this script, you need to
 1. Build 32-bit APK as usual.
-2. Build 64-bit APK with GN variable build_apk_secondary_abi=false.
+2. Build 64-bit APK with GN variable build_apk_secondary_abi=false OR true.
 3. Use this script to merge 2 APKs.
 
 """
@@ -53,9 +53,10 @@
   pass
 
 
-def UnpackApk(file_name, dst):
+def UnpackApk(file_name, dst, ignore_paths=()):
   zippy = zipfile.ZipFile(file_name)
-  zippy.extractall(dst)
+  files_to_extract = [f for f in zippy.namelist() if f not in ignore_paths]
+  zippy.extractall(dst, files_to_extract)
 
 
 def GetNonDirFiles(top, base_dir):
@@ -120,7 +121,7 @@
   # TODO(crbug.com/839191): Remove this once we're plumbing the lib correctly.
   missing_file_set = set(
       f for f in missing_file_set if not os.path.basename(f) ==
-      'libarcore_sdk_c_minimal.so')
+      'libarcore_sdk_c.so')
 
   errors = []
   if unexpected_file_set:
@@ -150,6 +151,15 @@
                                  compress=compress)
 
 
+def GetTargetAbiPath(apk_path, shared_library):
+  with zipfile.ZipFile(apk_path) as z:
+    matches = [p for p in z.namelist() if p.endswith(shared_library)]
+  if len(matches) != 1:
+    raise ApkMergeFailure('Found multiple/no libs for %s: %s' % (
+        shared_library, matches))
+  return matches[0]
+
+
 def GetSecondaryAbi(apk_zipfile, shared_library):
   ret = ''
   for name in apk_zipfile.namelist():
@@ -179,7 +189,7 @@
 
   # TODO(crbug.com/839191): we should pass this in via script arguments.
   if not args.loadable_module_32:
-    args.loadable_module_32.append('libarcore_sdk_c_minimal.so')
+    args.loadable_module_32.append('libarcore_sdk_c.so')
 
   for f in args.loadable_module_32:
     expected_files[f] = not args.uncompress_shared_libraries
@@ -188,7 +198,15 @@
     expected_files[f] = not args.uncompress_shared_libraries
 
   # need to unpack APKs to compare their contents
-  UnpackApk(args.apk_64bit, tmp_dir_64)
+  assets_path = 'base/assets' if args.bundle else 'assets'
+  exclude_files_64 = ['%s/snapshot_blob_32.bin' % assets_path,
+                      GetTargetAbiPath(args.apk_32bit, args.shared_library)]
+  # TODO(benmason): Remove when libcrashpad_handler.so
+  # is no longer a separate lib.
+  if 'libcrashpad_handler.so' in expected_files:
+    exclude_files_64.append(
+        GetTargetAbiPath(args.apk_32bit, 'libcrashpad_handler.so'))
+  UnpackApk(args.apk_64bit, tmp_dir_64, exclude_files_64)
   UnpackApk(args.apk_32bit, tmp_dir_32)
 
   ignores = ['META-INF', 'AndroidManifest.xml']
@@ -197,6 +215,10 @@
   if args.debug:
     # see http://crbug.com/648720
     ignores += ['webview_licenses.notice']
+  if args.bundle:
+    # if merging a bundle we must ignore the bundle specific
+    # proto files as they will always be different.
+    ignores += ['BundleConfig.pb', 'native.pb', 'resources.pb']
 
   dcmp = filecmp.dircmp(
       tmp_dir_64,
@@ -210,7 +232,7 @@
   CheckFilesExpected(diff_files, expected_files, args.component_build)
 
   with zipfile.ZipFile(tmp_apk, 'w') as out_zip:
-    exclude_patterns = ['META-INF/*']
+    exclude_patterns = ['META-INF/*'] + exclude_files_64
 
     # If there are libraries for which we don't want the 32 bit versions, we
     # should remove them here.
@@ -244,6 +266,7 @@
   parser.add_argument('--page-align-shared-libraries', action='store_true',
                       help='Obsolete, but remains for backwards compatibility')
   parser.add_argument('--uncompress-shared-libraries', action='store_true')
+  parser.add_argument('--bundle', action='store_true')
   parser.add_argument('--debug', action='store_true')
   # This option shall only used in debug build, see http://crbug.com/631494.
   parser.add_argument('--ignore-classes-dex', action='store_true')
diff --git a/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml b/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml
index 48dcdd41..80464d7 100644
--- a/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml
+++ b/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml
@@ -15,9 +15,7 @@
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
-        <!-- TODO(crbug.com/900912): Fix and remove lint ignore -->
         <EditText
-            tools:ignore="Autofill"
             android:id="@+id/url_field"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -25,7 +23,8 @@
             android:singleLine="true"
             android:inputType="textUri"
             android:selectAllOnFocus="true"
-            android:imeOptions="actionGo" />
+            android:imeOptions="actionGo"
+            android:importantForAutofill="no" />
         <ImageButton
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
diff --git a/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml b/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml
index ba7c79e..cc94cf2 100644
--- a/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml
+++ b/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml
@@ -11,6 +11,8 @@
     <item android:id="@+id/menu_enable_tracing"
           android:checkable="true"
           android:title="@string/menu_enable_tracing"/>
+    <item android:id="@+id/menu_print"
+          android:title="@string/menu_print"/>
     <item android:id="@+id/menu_about"
           android:title="@string/menu_about"/>
 </menu>
diff --git a/android_webview/tools/system_webview_shell/apk/res/values/strings.xml b/android_webview/tools/system_webview_shell/apk/res/values/strings.xml
index 066c150..7d74335 100644
--- a/android_webview/tools/system_webview_shell/apk/res/values/strings.xml
+++ b/android_webview/tools/system_webview_shell/apk/res/values/strings.xml
@@ -17,6 +17,7 @@
     <string name="menu_reset_webview">Destroy and create new WebView</string>
     <string name="menu_clear_cache">Clear cache</string>
     <string name="menu_enable_tracing">Enable tracing</string>
+    <string name="menu_print">Print</string>
     <string name="menu_about">About WebView</string>
     <string name="load_url">Load URL</string>
 </resources>
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 c3b0a7e..9bcf425 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
@@ -21,6 +21,9 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.StrictMode;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintManager;
 import android.provider.Browser;
 import android.util.SparseArray;
 import android.view.Gravity;
@@ -547,6 +550,12 @@
                     }
                 }
                 return true;
+            case R.id.menu_print:
+                PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
+                String jobName = "WebViewShell document";
+                PrintDocumentAdapter printAdapter = mWebView.createPrintDocumentAdapter(jobName);
+                printManager.print(jobName, printAdapter, new PrintAttributes.Builder().build());
+                return true;
             case R.id.menu_about:
                 about();
                 hideKeyboard(mUrlBar);
diff --git a/android_webview/utility/aw_content_utility_client.cc b/android_webview/utility/aw_content_utility_client.cc
index a1b8291..86c0988 100644
--- a/android_webview/utility/aw_content_utility_client.cc
+++ b/android_webview/utility/aw_content_utility_client.cc
@@ -4,15 +4,33 @@
 
 #include "android_webview/utility/aw_content_utility_client.h"
 
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "components/services/heap_profiling/heap_profiling_service.h"
 #include "components/services/heap_profiling/public/mojom/constants.mojom.h"
 #include "content/public/child/child_thread.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/simple_connection_filter.h"
+#include "content/public/utility/utility_thread.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 
 namespace android_webview {
 
+namespace {
+
+void TerminateThisProcess() {
+  content::UtilityThread::Get()->ReleaseProcess();
+}
+
+void RunHeapProfilerOnIOThread(service_manager::mojom::ServiceRequest request,
+                               base::OnceClosure terminate_process) {
+  service_manager::Service::RunAsyncUntilTermination(
+      std::make_unique<heap_profiling::HeapProfilingService>(
+          std::move(request)),
+      std::move(terminate_process));
+}
+
+}  // namespace
+
 AwContentUtilityClient::AwContentUtilityClient() = default;
 AwContentUtilityClient::~AwContentUtilityClient() = default;
 
@@ -26,13 +44,22 @@
       std::make_unique<content::SimpleConnectionFilter>(std::move(registry)));
 }
 
-void AwContentUtilityClient::RegisterServices(
-    AwContentUtilityClient::StaticServiceMap* services) {
-  service_manager::EmbeddedServiceInfo profiling_info;
-  profiling_info.task_runner = content::ChildThread::Get()->GetIOTaskRunner();
-  profiling_info.factory =
-      base::BindRepeating(&heap_profiling::HeapProfilingService::CreateService);
-  services->emplace(heap_profiling::mojom::kServiceName, profiling_info);
+bool AwContentUtilityClient::HandleServiceRequest(
+    const std::string& service_name,
+    service_manager::mojom::ServiceRequest request) {
+  if (service_name == heap_profiling::mojom::kServiceName) {
+    base::OnceClosure terminate_process =
+        base::BindOnce(base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
+                       base::SequencedTaskRunnerHandle::Get(), FROM_HERE,
+                       base::BindOnce(&TerminateThisProcess));
+    content::ChildThread::Get()->GetIOTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&RunHeapProfilerOnIOThread, std::move(request),
+                       std::move(terminate_process)));
+    return true;
+  }
+
+  return false;
 }
 
 }  // namespace android_webview
diff --git a/android_webview/utility/aw_content_utility_client.h b/android_webview/utility/aw_content_utility_client.h
index 667727c..7152a0c 100644
--- a/android_webview/utility/aw_content_utility_client.h
+++ b/android_webview/utility/aw_content_utility_client.h
@@ -18,7 +18,9 @@
 
   // content::ContentUtilityClient:
   void UtilityThreadStarted() override;
-  void RegisterServices(StaticServiceMap* services) override;
+  bool HandleServiceRequest(
+      const std::string& service_name,
+      service_manager::mojom::ServiceRequest request) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AwContentUtilityClient);
diff --git a/apps/BUILD.gn b/apps/BUILD.gn
index 75a2adf..bba3724c 100644
--- a/apps/BUILD.gn
+++ b/apps/BUILD.gn
@@ -48,9 +48,6 @@
   if (is_chromeos) {
     deps += [ "//components/user_manager" ]
   }
-
-  # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 }
 
 static_library("test_support") {
diff --git a/apps/launcher.cc b/apps/launcher.cc
index aeb55f7..0955e75 100644
--- a/apps/launcher.cc
+++ b/apps/launcher.cc
@@ -35,6 +35,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/granted_file_entry.h"
 #include "extensions/browser/lazy_background_task_queue.h"
+#include "extensions/browser/lazy_context_id.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/common/api/app_runtime.h"
 #include "extensions/common/extension.h"
@@ -293,7 +294,7 @@
         extensions::LazyBackgroundTaskQueue::Get(context_);
     if (queue->ShouldEnqueueTask(context_, app)) {
       queue->AddPendingTask(
-          context_, extension_id,
+          extensions::LazyContextId(context_, extension_id),
           base::Bind(&PlatformAppPathLauncher::GrantAccessToFilesAndLaunch,
                      this));
       return;
@@ -304,25 +305,28 @@
     ExtensionHost* const host =
         process_manager->GetBackgroundHostForExtension(extension_id);
     DCHECK(host);
-    GrantAccessToFilesAndLaunch(host);
+    GrantAccessToFilesAndLaunch(
+        std::make_unique<extensions::LazyContextTaskQueue::ContextInfo>(host));
   }
 
-  void GrantAccessToFilesAndLaunch(ExtensionHost* host) {
+  void GrantAccessToFilesAndLaunch(
+      std::unique_ptr<extensions::LazyContextTaskQueue::ContextInfo>
+          context_info) {
     const Extension* app = GetExtension();
     if (!app)
       return;
 
-    // If there was an error loading the app page, |host| will be NULL.
-    if (!host) {
+    // If there was an error loading the app page, |context_info| will be NULL.
+    if (!context_info) {
       LOG(ERROR) << "Could not load app page for " << extension_id;
       return;
     }
 
     std::vector<GrantedFileEntry> granted_entries;
     for (size_t i = 0; i < entry_paths_.size(); ++i) {
-      granted_entries.push_back(
-          CreateFileEntry(context_, app, host->render_process_host()->GetID(),
-                          entries_[i].path, entries_[i].is_directory));
+      granted_entries.push_back(CreateFileEntry(
+          context_, app, context_info->render_process_host->GetID(),
+          entries_[i].path, entries_[i].is_directory));
     }
 
     AppRuntimeEventRouter::DispatchOnLaunchedEventWithFileEntries(
diff --git